home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 1996 October: Mac OS SDK / Dev.CD Oct 96 SDK / Dev.CD Oct 96 SDK2.toast / Development Kits (Disc 2) / OpenDoc / OpenDoc Development / Debugging Support / OpenDoc Source Code / Storage / DragDrp.cpp < prev    next >
Encoding:
Text File  |  1996-04-22  |  91.1 KB  |  2,978 lines  |  [TEXT/MPS ]

  1. /*
  2.     File:        DragDrp.cpp
  3.  
  4.     Contains:    Implementation of ODDragAndDrop
  5.  
  6.     Owned by:    Vincent Lo
  7.  
  8.     Copyright:    © 1994 - 1996 by Apple Computer, Inc., all rights reserved.
  9.  
  10.     Change History (most recent first):
  11.  
  12.          <8>     4/16/96    DH        Fixed InWindow to ignore a null container.
  13.          <7>      4/9/96    DH        1308248: 1.0.2 Drag of no-part to trash
  14.                                     rejected. Used string resource for no-part
  15.                                     category instead of hard-coding it. Also
  16.                                     made filename of file in Trash when you
  17.                                     drop Nopart into the trash not be garbled.
  18.          <6>      4/8/96    DH        1338112: 1.0.2? Drag Hiliting Problems
  19.          <4>     3/29/96    DM        1296171: delay fatal Bento container errors
  20.                                     when inside drag manager
  21.          <3>     3/15/96    VL        1302780: Use GetFacetUnderPointForDrag
  22.                                     instead of GetFacetUnderPoint so that we
  23.                                     can drop within selection.
  24.          <2>     3/15/96    DH        287259 - 1.0.2 Don't get back what I put in
  25.                                     the scrapbook. Now writes out a memory
  26.                                     container to applications that it reloads
  27.                                     if it is found from Drag and Drop. Also
  28.                                     compatible with Clipboard container type.
  29.                                     1293781 - 1.0.2 DragWithin called out of
  30.                                     order. Fixed ODDragAndDropInWindow so that
  31.                                     it doesn't call DragLeave on the Containing
  32.                                     part unless the embedded part returns True
  33.                                     from DragEnter.
  34.         <84>    10/22/95    TÇ        1291419 GM: File type set incorrectly for
  35.                                     Old Mac data dragged to Finder from
  36.                                     OpenDoc.
  37.         <83>    10/13/95    TÇ        1284461 GM: Parts that are created in a
  38.                                     document should not automatically be given
  39.                                     names
  40.         <82>     10/8/95    TJ        Fixes Recomended by Refball
  41.         <81>     10/4/95    jpa        Added missing ODVolatiles [1285799]
  42.         <80>     10/4/95    VL        1287367: Added code in MySendDataProc to
  43.                                     check whether we are dragging to the trash.
  44.                                     1286642: Removed bogus kODPromiseFlavor.
  45.                                     Check for nil handle or invalid fsspec in
  46.                                     GetDropFSSpec. Added gIsResolvingPromise to
  47.                                     ensure that we know when we are fulfulling
  48.                                     a promise.
  49.         <79>     10/3/95    TJ        Changes done by RefBall Team
  50.         <78>     9/13/95    VL        Removed leftover debugstr from last
  51.                                     checkin.
  52.         <77>     9/13/95    VL        1283523: Dragging parts between Documents &
  53.                                     Finder needs to reflect new behavior. Added
  54.                                     a lot of apple event handlers.
  55.         <76>      9/8/95    VL        1275241, 1283463: Use
  56.                                     ODPlatformDragReference everywhere.
  57.         <75>      9/8/95    TÇ        1281096 FB2:Many constants in ODTypesB
  58.                                     without kOD prefix!
  59.         <74>      9/6/95    VL        1255735, 1274572: SetStationery in
  60.                                     SetFinderInfo. Set up finderFile in
  61.                                     EnterHandler to get the finder file info.
  62.                                     Removed CreateNewFile. Changed
  63.                                     MakeUniqueFilename to use resources for
  64.                                     localization and to follow the HI
  65.                                     guidelines.
  66.         <73>      9/1/95    CC        1273646, 1279220: CloneIntoFile: Use
  67.                                     kODCloneToFile.
  68.         <72>     8/30/95    EL        1279832: Storage THROW_IF_NULL problems.
  69.         <71>     8/29/95    VL        1276864, 1276541: Change result to
  70.                                     kODDropCopy if the original clone kind is
  71.                                     copy.
  72.         <70>     8/29/95    jpa        Univ Hdrs 2.1 fix [1279173]
  73.         <69>     8/22/95    VL        1265957, 1278381: If a part returns
  74.                                     kODFalse from DragEnter and DragWithin, try
  75.                                     the containing facet.
  76.         <68>     8/22/95    eeh        1276821:
  77.                                     kOpenDocShellSignature->kODShellSignature
  78.         <67>     8/21/95    VL        1274367: Removed WARN statement in
  79.                                     CopyFromDragItemInChunks.
  80.         <66>     8/17/95    CC        1199356: Turn off paste as attribute on
  81.                                     drop into background window.
  82.         <65>     8/17/95    CC        1277777: MyRecieveDropHandler: Set drop
  83.                                     result to kODDropFail when an exception is
  84.                                     caught.
  85.                                     Use ODVolatile(targetPart) or suffer
  86.                                     refcount error on failure.
  87.         <64>     8/16/95    jpa        Updated call to ODGetIconFamilyProp
  88.                                     [1212507]
  89.         <63>     8/16/95    VL        1244813: removed ASLMBUILD.
  90.         <62>     8/12/95    TÇ        1276812 Need to use TempObjs and TempRefs
  91.                                     for exception safety and to avoid TRY
  92.                                     blocks, 1276807 Opt./Bug: use StdTypIO
  93.                                     routines for portable streaming & smaller
  94.                                     footprint
  95.         <61>      8/3/95    RR        #1257260: Collapse B classes. Remove
  96.                                     somInit methods. Don't call IsInitialized
  97.                                     or SubclassResponsibility
  98.         <60>     7/21/95    VL        1270320: Dispose isoType returned from
  99.                                     GetISOTypeFromPlatformType.
  100.         <59>     6/28/95    VL        1190962, 1252228: Added code for creating
  101.                                     non-OD document.
  102.         <58>     6/26/95    VL        1262622: Call InitDateInfo in SetFinderInfo
  103.                                     to make sure that the modDate and
  104.                                     creationDate are set up.
  105.         <57>     6/25/95    VL        1255300: Added code for roundtrip D&D with
  106.                                     Finder (SetIconFamily and SetFinderInfo).
  107.         <56>     6/20/95    VL        1161434, 1194603: Reordered
  108.                                     AddDragItemFlavor to work around
  109.                                     interaction problems with Finder.
  110.         <55>      6/2/95    CC        1255476: MyReceiveDropHandler, EnterWindow,
  111.                                     InWindow: Release part acquired via
  112.                                     ODFrame::AquirePart.
  113.                                     1255474: AcquireStorageUnitOSType restored
  114.                                     to GetStorageUnitOSType.
  115.                                     1255474: AcquireSourceFrame restored to
  116.                                     GetSourceFrame.
  117.                                     1255474: AcquireSourcePart restored to
  118.                                     GetSourcePart.
  119.         <54>     5/26/95    VL        1251403: Multithreading naming support.
  120.         <53>     5/25/95    jpa        List.h --> LinkList.h [1253324]
  121.         <52>     5/18/95    CC        1250280: ShowPasteAsDialog throws on
  122.                                     invalid null arguments. 1238898: Add
  123.                                     destFrame argument to BeginClone call.
  124.         <51>     5/17/95    RR        #1250135/1250137/1250143 Getters increment
  125.                                     refcount
  126.         <50>     5/11/95    DM        #1246524, #1246529:
  127.                                     ValueNameSpaceGetEntry() must pass through
  128.                                     the value allocated.
  129.         <49>      5/5/95    CC        1246586: CloneIntoFile: Clone content frame
  130.                                     into document draft and create root frame
  131.                                     list property.
  132.         <49>      5/5/95    CC        1246586: CloneIntoFile: Clone content frame
  133.                                     into document draft and create root frame
  134.                                     list property.
  135.         <48>      5/2/95    CC        1207493: MyReceiveDropHandler: Call
  136.                                     SetDestFacet BEFORE targetFacet->Drop() so
  137.                                     CMDraft can get the target facet.
  138.         <47>      5/2/95    VL        1230557: Remove kODPropMouseDownOffset.
  139.         <46>     4/15/95    VL        1240014: Added TRY-CATCH blocks and turned
  140.                                     off debug statements.
  141.         <45>     4/14/95    VL        Temporarily turned on debug printf.
  142.         <44>     4/10/95    VL        1196870: Preserved HasLeftSourceFrame
  143.                                     behavior.
  144.         <43>     3/31/95    VL        1228756: Made dragdrop work with
  145.                                     non-persistent frame.
  146.         <42>     3/23/95    VL        1228275: ASSERT for null ODByteArray.
  147.         <41>     3/22/95    CC        1230322: Changed parameter to
  148.                                     ShowPasteAsDialog().
  149.         <40>     3/10/95    VL        1227218: Get rid of system heap.
  150.         <39>     2/28/95    VL        1194656: Check for existence before adding
  151.                                     property or value.
  152.         <38>      2/7/95    CC        1211295:  Pass isMove parameter to
  153.                                     ShowPasteAsDialog.
  154.         <37>      2/2/95    CC        1153802:  Added DragItemHasFlavor().
  155.                                     CopyFromDragItemInChunks() writese data at
  156.                                     current offset, instead of replacing the
  157.                                     entire value.
  158.                                     Automatically generate 'stxt' from
  159.                                     'styl'+'TEXT'; generate 'styl' from 'stxt'.
  160.         <36>      2/2/95    CG        #1195019:  ValueNameSpace entries are now
  161.                                     copied in and out instead of pointers being
  162.                                     passed around.
  163.         <35>      2/1/95    VL        1209010: Implemented more err checking.
  164.         <34>     1/26/95    VL        #???: Use updated Storage Unit Ref API.
  165.         <33>     1/23/95    CG        #1195019: ValueNameSpace methods now take
  166.                                     ODByteArray parameter instead of ODPtr.
  167.         <32>      1/9/95    VL        1195012, 1196957: StartDrag now takes
  168.                                     ODByteArray. Drag Attributes now returns
  169.                                     whether the nature of the drop.
  170.         <31>    12/20/94    VL        1195012: Make Storage calls be
  171.                                     marshallable.
  172.         <30>    12/13/94    VL        1203627,1200603,1203451,1198037,1194537,119
  173.                                     4755,1186815: Bug fixes.
  174.         <29>    11/14/94    VL        1194890: Enabled fulfulling multiple
  175.                                     promises.
  176.         <28>    10/19/94    VL        1162335: Now D&D adds a special value if
  177.                                     the dragged item is a non-OD file.
  178.         <27>    10/12/94    RA        Fix uninitilized variable.
  179.         <26>     10/4/94    VL        1162335: Added implementation on handling
  180.                                     non-OD files. Also chewed up MouseUp event
  181.                                     after drop.
  182.         <25>     9/29/94    RA        1189812: Mods for 68K build.
  183.         <24>     9/28/94    JBS        (for VL) 1162335: fixed unitialized
  184.                                     dataSize
  185.         <23>     9/27/94    VL        1142048: Do not call DragLeave if there is
  186.                                     a Drop.
  187.         <22>     9/26/94    VL        1162335: Enabled dragging from non-od docs.
  188.         <21>     9/23/94    VL        1155224: Drag to Finder names the drop
  189.                                     correctly. Also, enable dragging to trash.
  190.         <20>     9/23/94    VL        1184272: ContainerID is a sequence of
  191.                                     octets.
  192.         <19>     9/23/94    CC        1187509 - Implemented ShowPasteAsDialog().
  193.         <18>     9/15/94    VL        1184871: Fixed SendDataProc to handle
  194.                                     promises.
  195.         <17>     8/26/94    VL        1183174: Use updated cloning APIs.
  196.         <16>     8/17/94    jpa        (forgot bug# for <15>, which is 1181530)
  197.         <15>     8/17/94    jpa        ODDragAndDropsomUninit was calling parent's
  198.                                     somUninit twice!!
  199.         <14>     8/15/94    TÇ        #1180922 Removed most obsolete types from
  200.                                     StdTypes.idl
  201.         <13>     8/11/94    eeh        bug 1180486: MySendDataProc needs to call
  202.                                     SetDropResult
  203.         <12>     8/10/94    JBS        1179919: coordinate system bias changes
  204.         <11>      8/9/94    VL        1176710: Dragging an alias to OpenDoc
  205.                                     document now works. 1179857: DragEnter and
  206.                                     DragWithin return ODBoolean.
  207.         <10>      8/3/94    VL        1153123: Storage to ODStor.
  208.          <9>      8/2/94    CC        #1178169 - ShowPasteAsDialog() takes
  209.                                     ODFacet* instead of ODFrame*.
  210.          <8>     7/29/94    VL        THROW if D&D not installed.
  211.          <7>     7/27/94    CC        Touched to accompany .idl checkin.
  212.          <6>     7/26/94    VL        Reduced dependency on Bento and got rid of
  213.                                     DragAndDropStorageUnit.
  214.          <5>     7/21/94    VL        Made it run in SOM.
  215.          <4>      7/7/94    CC        Removed constants now defined by
  216.                                     ODTypesB.idl.
  217.          <3>      7/5/94    CC        MySendDataProc: Added blocks to case stmts
  218.                                     that were declaring locals at the scope of
  219.                                     the switch stmt.
  220.          <2>     6/30/94    jpa        Fixed some illegal implicit casts from
  221.                                     void*.
  222.          <1>     6/28/94    VL        first checked in
  223.  
  224.     To Do:        
  225.     In Progress:
  226. */
  227.  
  228. #ifndef _ALTPOINT_
  229. #include "AltPoint.h"            // Use C++ savvy ODPPoint and ODPRect
  230. #endif
  231.  
  232. #define ODDragAndDrop_Class_Source
  233. #define VARIABLE_MACROS
  234. #include <DragDrp.xih>
  235.  
  236. #ifndef SOM_ODDragItemIterator_xh
  237. #include <DgItmIt.xh>
  238. #endif
  239.  
  240. #ifndef _DRAGPRIV_
  241. #include <DragPriv.h>
  242. #endif
  243.  
  244. #ifndef _STORRSRC_
  245. #include <StorRsrc.h>
  246. #endif
  247.  
  248. #ifndef SOM_Module_OpenDoc_StdProps_defined
  249. #include <StdProps.xh>
  250. #endif
  251.  
  252. #ifndef SOM_Module_OpenDoc_StdTypes_defined
  253. #include <StdTypes.xh>
  254. #endif
  255.  
  256. #ifndef SOM_ODSession_xh
  257. #include <ODSessn.xh>
  258. #endif
  259.  
  260. #ifndef SOM_ODStorageSystem_xh
  261. #include <ODStor.xh>
  262. #endif
  263.  
  264. #ifndef SOM_ODContainer_xh
  265. #include <ODCtr.xh>
  266. #endif
  267.  
  268. #ifndef SOM_ODDocument_xh
  269. #include <Document.xh>
  270. #endif
  271.  
  272. #ifndef SOM_ODDraft_xh
  273. #include <Draft.xh>
  274. #endif
  275.  
  276. #ifndef SOM_ODFrame_xh
  277. #include <Frame.xh>
  278. #endif
  279.  
  280. #ifndef SOM_ODFacet_xh
  281. #include <Facet.xh>
  282. #endif
  283.  
  284. #ifndef SOM_ODWindow_xh
  285. #include <Window.xh>
  286. #endif
  287.  
  288. #ifndef SOM_ODWindowState_xh
  289. #include <WinStat.xh>
  290. #endif
  291.  
  292. #ifndef SOM_ODPart_xh
  293. #include <Part.xh>
  294. #endif
  295.  
  296. #ifndef SOM_ODTransform_xh
  297. #include <Trnsform.xh>
  298. #endif
  299.  
  300. #ifndef SOM_ODTranslation_xh
  301. #include <Translt.xh>
  302. #endif
  303.  
  304. #ifndef _ODMEMORY_
  305. #include "ODMemory.h"
  306. #endif
  307.  
  308. #ifndef _ODNew_
  309. #include "ODNew.h"
  310. #endif
  311.  
  312. #ifndef _EXCEPT_
  313. #include "Except.h"
  314. #endif
  315.  
  316. #ifndef _LINKLIST_
  317. #include "LinkList.h"
  318. #endif
  319.  
  320. #ifndef SOM_ODStorageUnitView_xh
  321. #include <SUView.xh>
  322. #endif
  323.  
  324. #ifndef _STORDEF_
  325. #include "StorDef.h"
  326. #endif
  327.  
  328. #ifndef SOM_CMStorageUnit_xh
  329. #include <CMSU.xh>
  330. #endif
  331.  
  332. #ifndef _PLFMFILE_
  333. #include <PlfmFile.h>
  334. #endif
  335.  
  336. #ifndef _CONSTDEF_
  337. #include "ConstDef.h"
  338. #endif
  339.  
  340. #ifndef _PASCLSTR_
  341. #include <PasclStr.h>
  342. #endif
  343.  
  344. #ifndef SOM_Module_OpenDoc_StdDefs_defined
  345. #include "StdDefs.xh"
  346. #endif
  347.  
  348. #ifndef _LINKDLGS_
  349. #include "LinkDlgs.h"
  350. #endif
  351.  
  352. #ifndef __MEMORY__
  353. #include <Memory.h>
  354. #endif
  355.  
  356. #ifndef __GESTALTEQU__
  357. #include <GestaltEqu.h>
  358. #endif
  359.  
  360. #ifndef __TOOLUTILS__
  361. #include <ToolUtils.h>
  362. #endif
  363.  
  364. #ifndef __ERRORS__
  365. #include <Errors.h>
  366. #endif
  367.  
  368. #ifndef __SCRIPT__
  369. #include <Script.h>
  370. #endif
  371.  
  372. #ifndef __PACKAGES__
  373. #include <Packages.h>
  374. #endif
  375.  
  376. #ifndef __APPLEEVENTS__
  377. #include <AppleEvents.h>
  378. #endif
  379.  
  380. #ifndef _ISOSTR_
  381. #include <ISOStr.h>
  382. #endif
  383.  
  384. #ifndef __ALIASES__
  385. #include <Aliases.h>
  386. #endif
  387.  
  388. #ifndef __FOLDERS__
  389. #include <Folders.h>
  390. #endif
  391.  
  392. #ifndef _BARRAY_
  393. #include <BArray.h>
  394. #endif
  395.  
  396. #ifndef SOM_ODNameSpaceManager_xh
  397. #include <NmSpcMg.xh>
  398. #endif
  399.  
  400. #ifndef SOM_ODValueNameSpace_xh
  401. #include <ValueNS.xh>
  402. #endif
  403.  
  404. #ifndef _TEMPOBJ_
  405. #include <TempObj.h>
  406. #endif
  407.  
  408. #ifndef _STORUTIL_
  409. #include "StorUtil.h"
  410. #endif
  411.  
  412. #include <string.h>
  413.  
  414. #ifndef _ODDEBUG_
  415. #include "ODDebug.h"
  416. #endif
  417.  
  418. #ifndef _NMSPCUTL_
  419. #include <NmSpcUtl.h>
  420. #endif
  421.  
  422. #ifndef _STDTYPIO_
  423. #include <StdTypIO.h>
  424. #endif
  425.  
  426. #ifndef __DIALOGS__
  427. #include <Dialogs.h>
  428. #endif
  429.  
  430. #ifndef _INFOUTIL_
  431. #include <InfoUtil.h>
  432. #endif
  433.  
  434. #ifndef __ICONS__
  435. #include <Icons.h>
  436. #endif
  437.  
  438. #ifndef __FINDER__
  439. #include <Finder.h>
  440. #endif
  441.  
  442. #ifndef _POUTILS_
  443. #include <POUtils.h>
  444. #endif
  445.  
  446. #ifndef _OPENHASH_
  447. #include <OpenHash.h>
  448. #endif
  449.  
  450. #ifndef _ITEXT_
  451. #include <IText.h>
  452. #endif
  453.  
  454. #ifndef _USERSRCM_
  455. #include <UseRsrcM.h>
  456. #endif
  457.  
  458. #ifndef _DLOGUTIL_
  459. #include <DlogUtil.h>
  460. #endif
  461.  
  462. #ifndef _DRGDPDEF_
  463. #include "DrgDpDef.h"
  464. #endif
  465.  
  466. #ifndef __DIALOGS__
  467. #include <Dialogs.h>
  468. #endif
  469.  
  470. static FSSpec gTmpFileFSSpec;
  471. static FSSpec gTargetFSSpec;
  472. static boolean gIsResolvingPromise = kODFalse;
  473.  
  474. //==============================================================================
  475. // Constants
  476. //==============================================================================
  477.  
  478. #define kODUserPromiseFlavor    0x66696c65    // 'file'
  479. //#define kODBentoFlavor    0x626E746F    // 'bnto'
  480. // The Bento container flavor was changed to odcn so we have compatibility with
  481. // the clipboard.
  482. #define kODBentoFlavor        0x6F64636E    // 'odcn'
  483. #define kODPromiseFlavor    0x70726D73    // 'prms'
  484. #define kODPromiseDesc        0x70726D73    // 'prms'
  485. #define kODScrapTypestyl    0x7374796c    // 'styl'
  486. #define kODScrapTypestxt    0x73747874    // 'stxt'
  487. #define kODScrapTypeTEXT    0x54455854    // 'TEXT'
  488.  
  489. #define kODDropHasLeftSourceFrameMask    ~kODDropIsInSourceFrame
  490. #define kODDragHasLeftSourcePartMask    ~(kODDropIsInSourceFrame | kODDropIsInSourcePart)
  491.  
  492. // #define kODDestinationFileSpec 'dfss'
  493. // #define kODSourceFileSpec 'sfss'
  494. // #define kODPreReplaceFileEventID 'prfl'
  495. // const FourCharCode kODReplaceFileEventID = 'rfl ';
  496. // #define kODSession 'sess'
  497.  
  498. #define kODDestinationFileSpec 'DFSS'
  499. #define kODSourceFileSpec 'SFSS'
  500. #define kODReplaceFileEventID 'RFL '
  501. #define kODSession 'SESS'
  502.  
  503. const ODULong    kODInitialNumEntries = 8;
  504.  
  505. #if ODDebug
  506. // #define ODDebug_DragAndDrop 1
  507. #endif
  508.  
  509. //==============================================================================
  510. // Scalar Types
  511. //==============================================================================
  512.  
  513. typedef struct {
  514.     ODPart            *sourcePart;
  515.     ODStorageUnitView *destSUView;
  516. } ODPromiseDesc;
  517.  
  518. #define IsOpenDocDocument(osType) ((osType != 'APPL') && (osType != 'shlb'))
  519. #define SetPasteAsAttribute(self, ev, m) do {if ((m & cmdKey) && IsFrontProcess()) self->SetAttributes(ev, self->GetAttributes(ev) | kODDropIsPasteAs);} while (0)
  520.  
  521. //==============================================================================
  522. // Prototyping
  523. //==============================================================================
  524.  
  525. extern ODBoolean gODBentoFatalErrorHasOccurred; // SessHdr.cpp
  526. extern ODBoolean gODDelayBentoFatalError; // SessHdr.cpp
  527. extern ODBoolean gODSuppressBentoFatalError; // SessHdr.cpp
  528. extern void ODBentoFatalError(); // SessHdr.cpp
  529.  
  530. static pascal OSErr MyDragTrackingHandler(
  531.         short message,
  532.         WindowPtr theWindow,
  533.         void* handlerRefCon,
  534.         ODPlatformDragReference theDrag);
  535.  
  536. static pascal OSErr    MyReceiveDropHandler(
  537.         WindowPtr theWindow,
  538.         void* handlerRefCon,
  539.         ODPlatformDragReference theDrag);
  540.  
  541. static pascal OSErr  MySendDataProc(
  542.         FlavorType theType,
  543.         void* refCon,
  544.         ItemReference theItem,
  545.         ODPlatformDragReference theDrag);
  546.  
  547. static OSErr ODPascal ReplaceFileAEHandler(
  548.         const AppleEvent* replaceFileEvent,
  549.         AppleEvent* reply,
  550.         long refCon);
  551.         
  552. static void RespecifyToTempFolder(PlatformFile* file);
  553. static OSErr CreateReplaceFileEvent(Environment* ev, AppleEvent* replaceFileEvent, ODSession* session, ProcessSerialNumber* psn);
  554. static OSErr SetupReplaceFileEvent(Environment* ev, AppleEvent* replaceFileEvent, FSSpec* sourceFileSpec, FSSpec* destFileSpec);
  555. static OSErr SendReplaceFileEvent(AppleEvent* replaceFileEvent, ProcessSerialNumber* psn);
  556. static OSErr DisposeReplaceFileEvent(AppleEvent* replaceFileEvent);
  557. static ODBoolean DragItemHasFlavor(ODPlatformDragReference theDrag, ItemReference itemID, OSType    theType);
  558. static OSErr CloneIntoFile(Environment* ev, ODDragItem* theDragItem, FSSpec dropFSSpec); 
  559. static void CloneIntoFlavor(Environment* ev, ODDragAndDrop* dad, ODDragItem* theDragItem, 
  560.                                 ODPlatformDragReference theDrag, ItemReference theItem, FlavorType theType,
  561.                                 FSSpec dropFSSpec);
  562. static boolean MakeUniqueFilename( Environment *ev, ODSession* session, ODStorageUnit *su, FSSpec *spec );
  563. static OSType GetStorageUnitOSType( Environment *ev, ODStorageUnit *su );
  564. static OSErr CopyToDragItemInChunks(Environment* ev,
  565.                                 FlavorType theType,
  566.                                 ItemReference theItem,
  567.                                 ODPlatformDragReference theDrag,
  568.                                 ODDragItem* theDragItem);
  569. static OSErr CopyFromDragItemInChunks(Environment* ev,
  570.                                 FlavorType theType,
  571.                                 ItemReference theItem,
  572.                                 ODPlatformDragReference theDrag,
  573.                                 ODStorageUnitView* destSUView);
  574.  
  575. static OSErr CopyMemContainerToDragItemInChunks(Environment* ev,
  576.                                 ODSession* theSession,
  577.                                 FlavorType theType,
  578.                                 ItemReference theItem,
  579.                                 ODPlatformDragReference theDrag,
  580.                                 ODDragItem* theDragItem);
  581.  
  582. static ODHandle CloneToTempMemContainer( Environment* ev, ODMemDragItem* tempDItem, ODSession* theSession );
  583. static void SetFinderInfo(Environment* ev, ODStorageUnit* su, PlatformFile* file);
  584. static void    SetIconFamily(Environment* ev, ODStorageUnit* fromSU, PlatformFile* file);
  585. static OSErr GetDropFSSpec(ODPlatformDragReference theDrag, FSSpec& dropFSSpec);
  586. static boolean IsTrashFolder(FSSpec dropFSSpec);
  587. static boolean IsFrontProcess();
  588.  
  589. #ifdef ODDebug_DragAndDrop
  590.  
  591. #ifndef SOM_ODStorageUnitCursor_xh
  592. #include <SUCursor.xh>
  593. #endif
  594.  
  595. void PrintDragReference(ODPlatformDragReference dragRef, char* header);
  596. void PrintStorageUnit(Environment* ev, ODStorageUnit* su, char* header);
  597. #endif
  598.  
  599. #pragma segment ODDragAndDrop
  600.  
  601. #include "DragDrpB.cpp"    // Platform-independent methods, if any
  602.  
  603.  
  604. SOM_Scope ODBoolean  SOMLINK ODDragAndDropShowPasteAsDialog(ODDragAndDrop *somSelf, Environment *ev,
  605.         ODBoolean canPasteLink,
  606.         ODPasteAsMergeSetting mergeSetting,
  607.         ODFacet* facet,
  608.         ODTypeToken viewType,
  609.         ODStorageUnit* contentSU,
  610.         ODPasteAsResult* result)
  611. {
  612.     ODDragAndDropData *somThis = ODDragAndDropGetData(somSelf);
  613.     ODDragAndDropMethodDebug("ODDragAndDrop","ODDragAndDropShowPasteAsDialog");
  614.  
  615.     SOM_CATCH return kODFalse;
  616.  
  617.     THROW_IF_NULL(facet, kODErrNullFacetInput);
  618.     THROW_IF_NULL(contentSU, kODErrIllegalNullStorageUnitInput);
  619.     THROW_IF_NULL(result, kODErrNullPasteAsResultInput);
  620.  
  621.     ODBoolean returnValue = ShowPasteAsDialog(
  622.                                 canPasteLink, 
  623.                                 mergeSetting,
  624.                                 (somSelf->GetDropResult(ev) == kODDropMove),
  625.                                 contentSU,
  626.                                 facet, 
  627.                                 viewType, 
  628.                                 result);
  629.  
  630.     return returnValue;
  631. }
  632.  
  633. SOM_Scope void  SOMLINK ODDragAndDropInitDragAndDrop(ODDragAndDrop *somSelf, Environment *ev,
  634.         ODSession* session)
  635. {
  636.     ODDragAndDropData *somThis = ODDragAndDropGetData(somSelf);
  637.     ODDragAndDropMethodDebug("ODDragAndDrop","ODDragAndDropInitDragAndDrop");
  638.  
  639. SOM_TRY
  640.  
  641.     /* Moved from somInit. SOM itself sets fields to zero
  642.     _fSession = kODNULL;
  643.     _fWindowState = kODNULL;
  644.     _fStorageSystem = kODNULL;
  645.  
  646.     _fDragItemList = kODNULL;
  647.     _fListFromHandler = false;
  648.     _fDragItemIterator = kODNULL;
  649.     
  650.     _fAttributes = 0;
  651.     _fDragReference = 0;
  652.  
  653.     _fPrevFacet = kODNULL;
  654.     _fSourceFrame = kODNULL;
  655.     _fSourcePart = kODNULL;
  656.     _fDestFacet = kODNULL;
  657.     
  658.     _fReceiveHandler = kODNULL;
  659.     _fTrackingHandler = kODNULL;
  660.     _fSendDataHandler = kODNULL;
  661.     _fFacetsRejected = kODNULL;
  662.     */
  663.  
  664.     _fSession = session;
  665.  
  666.     somSelf->InitObject(ev);
  667.     
  668.     long  gestaltResult;
  669.     OSErr result;
  670.  
  671.     // Get the current process for background drag
  672.     _fPSN = (ProcessSerialNumber*) ODNewPtr(sizeof(ProcessSerialNumber));
  673.     GetCurrentProcess(_fPSN);
  674.     
  675.     _fReplaceFileEvent = (AppleEvent*) ODNewPtr(sizeof(AppleEvent));
  676.     CreateReplaceFileEvent(ev,
  677.         _fReplaceFileEvent,
  678.         session,
  679.         _fPSN);
  680.  
  681.     _fFacetsRejected = new OpenHashTable(OpenHashTable::StdEqual, OpenHashTable::StdHash, kODNULL);
  682.     _fFacetsRejected->Initialize(kODInitialNumEntries,
  683.                                     sizeof(ODFacet*),
  684.                                     sizeof(ODFacet*));
  685.         
  686.     // Check if the drag manager is present
  687.     result = Gestalt(gestaltDragMgrAttr, &gestaltResult);
  688.     if (result != noErr)
  689.         THROW_M(result, "Error from Gestalt");
  690.  
  691.     // The mysterious 31 is the bit position as BitTst uses a convention opposite to MC68000
  692.     if (BitTst(&gestaltResult, (31 - gestaltDragMgrPresent)) == false) {
  693.         THROW_M(kODErrNoDragManager, "No drag manager present");
  694.     }
  695.     else {
  696.         // Install the default tracking handler for this application (session)
  697.         _fTrackingHandler = NewDragTrackingHandlerProc(&MyDragTrackingHandler);
  698.         result = InstallTrackingHandler(_fTrackingHandler, NULL, (void *) somSelf);
  699.         ASSERTM(result == noErr, result, "Error from InstallTrackingHandler");
  700.         
  701.         // Install the default receive handler for this application (session)
  702.         _fReceiveHandler = NewDragReceiveHandlerProc(&MyReceiveDropHandler);
  703.         result = InstallReceiveHandler(_fReceiveHandler, NULL, (void *) somSelf);
  704.         ASSERTM(result == noErr, result, "Error from InstallReceiveHandler");
  705.     
  706.         // Create a UPP for MySendDataProc which we will use later inside ::StartDrag
  707.         _fSendDataHandler = NewDragSendDataProc(MySendDataProc);
  708.     
  709.         _fWindowState = _fSession->GetWindowState(ev);
  710.     
  711.         _fStorageSystem = _fSession->GetStorageSystem(ev);
  712.     
  713.         _fDragItemList = new LinkedList;
  714.  
  715.         AEEventHandlerUPP theHandlerUPP = NewAEEventHandlerProc( ReplaceFileAEHandler ) ;
  716.         THROW_IF_ERROR(AEInstallEventHandler(kODShellSignature,
  717.                 kODReplaceFileEventID, theHandlerUPP, nil, false));
  718.     }
  719.  
  720. SOM_CATCH_ALL
  721.  
  722.     _fWindowState = kODNULL;
  723.     _fStorageSystem = kODNULL;
  724.     if (_fDragItemList)
  725.     {
  726.         delete _fDragItemList;
  727.         _fDragItemList = kODNULL;
  728.     }
  729.     if (_fReceiveHandler)
  730.     {
  731.         RemoveReceiveHandler(_fReceiveHandler, NULL);
  732.         DisposeRoutineDescriptor(_fReceiveHandler);
  733.         _fReceiveHandler = kODNULL;
  734.     }
  735.     if (_fTrackingHandler)
  736.     {
  737.         RemoveTrackingHandler(_fTrackingHandler, NULL);
  738.         DisposeRoutineDescriptor(_fTrackingHandler);
  739.         _fTrackingHandler = kODNULL;
  740.     }
  741.     if (_fSendDataHandler)
  742.     {
  743.         DisposeRoutineDescriptor(_fSendDataHandler);
  744.         _fSendDataHandler = kODNULL;
  745.     }
  746.  
  747. SOM_ENDTRY
  748. }
  749.  
  750. SOM_Scope ODULong  SOMLINK ODDragAndDropGetDragAttributes(ODDragAndDrop *somSelf, Environment *ev)
  751. {
  752.     ODDragAndDropData *somThis = ODDragAndDropGetData(somSelf);
  753.     ODDragAndDropMethodDebug("ODDragAndDrop","ODDragAndDropGetDragAttributes");
  754.  
  755.     if (_fTrackingHandler == kODNULL)
  756.         ODSetSOMException(ev, kODErrNoDragManager);
  757.  
  758.     return _fAttributes;
  759. }
  760.  
  761. SOM_Scope ODPlatformDragReference  SOMLINK ODDragAndDropGetDragReference(ODDragAndDrop *somSelf, Environment *ev)
  762. {
  763.     ODDragAndDropData *somThis = ODDragAndDropGetData(somSelf);
  764.     ODDragAndDropMethodDebug("ODDragAndDrop","ODDragAndDropGetDragReference");
  765.  
  766.     if (_fTrackingHandler == kODNULL)
  767.         ODSetSOMException(ev, kODErrNoDragManager);
  768.         
  769.     return _fDragReference;
  770. }
  771.  
  772.  
  773. SOM_Scope ODFacet*  SOMLINK ODDragAndDropFindTargetFacet(ODDragAndDrop *somSelf, Environment *ev,
  774.         ODPlatformWindow theWindow,
  775.         ODPoint* mouse,
  776.         ODPoint* localMouse)
  777. {
  778.     ODDragAndDropData *somThis = ODDragAndDropGetData(somSelf);
  779.     ODDragAndDropMethodDebug("ODDragAndDrop","ODDragAndDropFindTargetFacet");
  780.  
  781.     ODFacet   *targetFacet = kODNULL;
  782.     
  783.     if (_fTrackingHandler == kODNULL)
  784.         ODSetSOMException(ev, kODErrNoDragManager);
  785.     else {
  786.         SOM_TRY
  787.             ODFacet   *curFacet;
  788.             GrafPtr        curPort;
  789.             Point        qdLocal;
  790.             
  791.             {    TempODWindow targetWindow = _fWindowState->AcquireODWindow(ev,theWindow);
  792.                 if (!targetWindow)
  793.                     return kODNULL;
  794.             
  795.                 GetPort(&curPort);
  796.                 SetPort(theWindow);
  797.                 qdLocal = mouse->AsQDPoint();
  798.                 GlobalToLocal(&qdLocal);
  799.                 *localMouse = qdLocal;
  800.                 
  801.                 SetPort(curPort);
  802.             
  803.                 curFacet = targetWindow->GetFacetUnderPointForDrag(ev,
  804.                         localMouse);
  805.             }
  806.             
  807.             while (curFacet && !targetFacet)
  808.             {
  809.                 ODFrame* curFrame = curFacet->GetFrame(ev);
  810.                 if (!curFrame->IsDragging(ev) &&
  811.                     curFrame->IsDroppable(ev) &&
  812.                     !curFrame->IsFrozen(ev) &&
  813.                     !_fFacetsRejected->Exists(&curFacet))
  814.                 {
  815.                     targetFacet = curFacet;
  816.                 }
  817.                 curFacet = curFacet->GetContainingFacet(ev);
  818.             }
  819.             
  820.         SOM_CATCH_ALL
  821.         SOM_ENDTRY
  822.     }
  823.     return targetFacet;
  824. }
  825.  
  826. SOM_Scope void  SOMLINK ODDragAndDropGetPromiseFromDragManager(ODDragAndDrop *somSelf, Environment *ev,
  827.         ODPart* sourcePart,
  828.         ODStorageUnitView* destSUView)
  829. {
  830.     ODDragAndDropData *somThis = ODDragAndDropGetData(somSelf);
  831.     ODDragAndDropMethodDebug("ODDragAndDrop","ODDragAndDropGetPromiseFromDragManager");
  832.  
  833.     SOM_TRY
  834.     
  835.     if (_fTrackingHandler == kODNULL)
  836.         THROW(kODErrNoDragManager);
  837.  
  838.     OSErr            err;
  839.     
  840.     if (sourcePart != kODNULL) {
  841.  
  842.         ItemReference    dragItemRef;
  843.         err = GetDragItemReferenceNumber(_fDragReference, 1, &dragItemRef);
  844.         ASSERTM(err == noErr, err, "Cannot get drag item reference in GetPromiseFromDragManager");
  845.  
  846.         ODPromiseDesc    theInfo;
  847.         theInfo.sourcePart = sourcePart;
  848.         theInfo.destSUView = destSUView;
  849.         
  850.         // Set the offset of the suview to the beginning of the value
  851.         destSUView->SetOffset(ev, 0);
  852.                 
  853.         AEDesc            dropLocation;
  854.         err = AECreateDesc(kODPromiseDesc, (Ptr) &theInfo, sizeof(theInfo), &dropLocation);
  855.         ASSERTM(err == noErr, err, "Error from AECreateDesc in GetPromiseFromDragManager");
  856.     
  857.         err = SetDropLocation(_fDragReference, &dropLocation);
  858.         ASSERTM(err == noErr, err, "Error from SetDropLocation in GetPromiseFromDragManager");
  859.  
  860.         gIsResolvingPromise = kODTrue;
  861.  
  862.         long            resolveResult;
  863.         Size            resolveSize = sizeof(long);
  864.         
  865.         err = GetFlavorData(_fDragReference, dragItemRef, kODPromiseFlavor, &resolveResult, &resolveSize, 0);
  866.         ASSERTM(err == cantGetFlavorErr, err, "Cannot GetFlavorData in GetPromiseFromDragManager");
  867.         
  868.         AEDisposeDesc(&dropLocation);
  869.     
  870.         // Reset the Drop location.
  871.  
  872.         gIsResolvingPromise = kODFalse;
  873.         
  874.         theInfo.sourcePart = kODNULL;
  875.         theInfo.destSUView = kODNULL;
  876.         
  877.         err = AECreateDesc(kODPromiseDesc, (Ptr) &theInfo, 0, &dropLocation);
  878.         ASSERTM(err == noErr, err, "Error from AECreateDesc in GetPromiseFromDragManager");
  879.         
  880.         err = SetDropLocation(_fDragReference, &dropLocation);
  881.         ASSERTM(err == noErr, err, "Error from SetDropLocation in GetPromiseFromDragManager");
  882.         
  883.         AEDisposeDesc(&dropLocation);
  884.     }
  885.     else {
  886.         ODHandle dataHandle = kODNULL;
  887.         ODType isoType = kODNULL;
  888.         TRY
  889.         
  890.             ODTranslation*    translate  = _fSession->GetTranslation(ev);
  891.             isoType = destSUView->GetType(ev);
  892.             if (ODISOStrNCompare((ODISOStr) isoType,(ODISOStr) kODAppleFileTypePrefix, ODISOStrLength(kODAppleFileTypePrefix)) != 0) {
  893.                 ItemReference   theItem;
  894.                 OSErr result;
  895.                 destSUView->SetOffset(ev,0);
  896.                 StorageUnitViewGetValue(destSUView, ev, sizeof(ItemReference), &theItem);            
  897.                 ODPlatformType platformType = translate->GetPlatformTypeFromISOType(ev, isoType);            
  898.                 if ( platformType == kODScrapTypestxt && !DragItemHasFlavor(_fDragReference, theItem, kODScrapTypestxt) )
  899.                 {
  900.                     // Create styled text from 'styl' and 'TEXT' flavors
  901. #ifdef ODDebug_DragAndDrop
  902.                     somPrintf("GetPromiseFromDragManager: Creating 'stxt' from 'styl' and 'TEXT'\n");
  903. #endif
  904.                     destSUView->SetOffset(ev,0);
  905.                     result = CopyFromDragItemInChunks(ev, kODScrapTypestyl, theItem, _fDragReference, destSUView);
  906.                     destSUView->SetOffset(ev, destSUView->GetSize(ev));
  907.                     result = CopyFromDragItemInChunks(ev, kODScrapTypeTEXT, theItem, _fDragReference, destSUView);
  908.                 }
  909.                 else
  910.                 {        
  911.                     destSUView->SetOffset(ev,0);
  912.                     result = CopyFromDragItemInChunks(ev, platformType, theItem, _fDragReference, destSUView);
  913.                 }
  914.             }
  915.             ODDisposePtr(isoType);
  916.         
  917.         CATCH_ALL
  918.         
  919.             if (dataHandle)
  920.                 ODDisposeHandle(dataHandle);
  921.             if (isoType)
  922.                 ODDisposePtr(isoType);
  923.             RERAISE;
  924.         
  925.         ENDTRY
  926.     }
  927.     
  928.     SOM_CATCH_ALL
  929.     SOM_ENDTRY
  930. }
  931.  
  932. SOM_Scope void  SOMLINK ODDragAndDropGetDataFromDragManager(ODDragAndDrop *somSelf, Environment *ev,
  933.         ODStorageUnitView*    suView)
  934. {
  935.     ODDragAndDropData *somThis = ODDragAndDropGetData(somSelf);
  936.     ODDragAndDropMethodDebug("ODDragAndDrop","ODDragAndDropGetDataFromDragManager");
  937.     
  938.     WARN("ODDragAndDropGetDataFromDragManager is obsoleted.\n");
  939. }
  940.  
  941. SOM_Scope void  SOMLINK ODDragAndDropsomUninit(ODDragAndDrop *somSelf)
  942. {
  943.     ODDragAndDropData *somThis = ODDragAndDropGetData(somSelf);
  944.     ODDragAndDropMethodDebug("ODDragAndDrop","ODDragAndDropsomUninit");
  945.  
  946.     if (_fDragItemList)
  947.     {
  948.         _fDragItemList->DeleteAllLinks();
  949.         delete _fDragItemList;
  950.     }
  951.     if (_fDragItemIterator)
  952.         delete _fDragItemIterator;
  953.     if (_fReceiveHandler)
  954.     {
  955.         RemoveReceiveHandler(_fReceiveHandler, NULL);
  956.         DisposeRoutineDescriptor(_fReceiveHandler);
  957.     }
  958.     if (_fTrackingHandler)
  959.     {
  960.         RemoveTrackingHandler(_fTrackingHandler, NULL);
  961.         DisposeRoutineDescriptor(_fTrackingHandler);
  962.     }
  963.     if (_fSendDataHandler)
  964.     {
  965.         DisposeRoutineDescriptor(_fSendDataHandler);
  966.     }
  967.     
  968.     ODDeleteObject(_fFacetsRejected);
  969.     
  970.     ODDisposePtr(_fPSN);
  971.     ODDisposePtr(_fReplaceFileEvent);
  972. }
  973.  
  974. SOM_Scope void  SOMLINK ODDragAndDropClear(ODDragAndDrop *somSelf, Environment *ev)
  975. {
  976.     ODDragAndDropData *somThis = ODDragAndDropGetData(somSelf);
  977.     ODDragAndDropMethodDebug("ODDragAndDrop","ODDragAndDropClear");
  978.  
  979. #if ODDebug_DragAndDrop
  980.     somPrintf("In Clear\n");
  981. #endif
  982.  
  983.     if (_fTrackingHandler == kODNULL)
  984.         ODSetSOMException(ev, kODErrNoDragManager);
  985.     else {
  986.         SOM_TRY
  987.             if (_fDragItemIterator)
  988.             {
  989.                 delete _fDragItemIterator;
  990.                 _fDragItemIterator = kODNULL;
  991.             }
  992.             _fDragItemList->DeleteAllLinks();
  993.         SOM_CATCH_ALL
  994.         SOM_ENDTRY
  995.     }
  996. }
  997.  
  998. SOM_Scope ODStorageUnit*  SOMLINK ODDragAndDropGetContentStorageUnit(ODDragAndDrop *somSelf, Environment *ev)
  999. {
  1000.     ODDragAndDropData *somThis = ODDragAndDropGetData(somSelf);
  1001.     ODDragAndDropMethodDebug("ODDragAndDrop","ODDragAndDropGetContentStorageUnit");
  1002.  
  1003.     ODStorageUnit* contentSU = kODNULL;
  1004.     
  1005.     if (_fTrackingHandler == kODNULL)
  1006.         ODSetSOMException(ev, kODErrNoDragManager);
  1007.     else {
  1008.         SOM_TRY
  1009.  
  1010.             ODMemDragItem    *newItem;
  1011.             ODDragLink        *newLink;
  1012.         
  1013.             newItem = new(ODGetDefaultHeap()) ODMemDragItem(_fStorageSystem, kODFalse);
  1014.             ASSERTM(newItem != kODNULL, kODErrCannotAllocateDragItem, "Error allocating drag item");
  1015.             newItem->Initialize(ev);
  1016.             newLink = new ODDragLink(newItem, kODTrue);
  1017.             if (!newLink)
  1018.             {
  1019.                 delete newItem;
  1020.                 ASSERTM(newLink != kODNULL, kODErrCannotAllocateDragItem, "Error allocating drag link");
  1021.             }
  1022.             _fDragItemList->AddLast(newLink);
  1023.             contentSU = newItem->fSU;
  1024.             
  1025.         SOM_CATCH_ALL
  1026.         SOM_ENDTRY
  1027.     }
  1028.     return contentSU;
  1029. }
  1030.  
  1031. SOM_Scope ODDropResult  SOMLINK ODDragAndDropStartDrag(ODDragAndDrop *somSelf, Environment *ev,
  1032.         ODFrame* srcFrame,
  1033.         ODType imageType,
  1034.         ODByteArray* image,
  1035.         ODPart** destPart,
  1036.         ODByteArray* refCon)
  1037. {
  1038.     ODDragAndDropData *somThis = ODDragAndDropGetData(somSelf);
  1039.     ODDragAndDropMethodDebug("ODDragAndDrop","ODDragAndDropStartDrag");
  1040.  
  1041.     LinkedListIterator *theIter = kODNULL;    ODVolatile(theIter);
  1042.  
  1043. SOM_TRY
  1044.     if (_fTrackingHandler == kODNULL)
  1045.         THROW(kODErrNoDragManager);
  1046.  
  1047.     ASSERT(image != kODNULL, kODErrIllegalNullInput);
  1048.     ASSERT(refCon != kODNULL, kODErrIllegalNullInput);
  1049.  
  1050.     OSErr               result;
  1051.     RgnHandle           imageRgn;
  1052.     ODTranslation     *translate;
  1053.     ODULong            count, index;
  1054.     ODType             theISOType;
  1055.     ODPlatformType     platformType;
  1056.     PromiseHFSFlavor    thePromise;
  1057.     ODStorageUnit     *theSU;
  1058.     ODDragLink        *theDragLink;
  1059.  
  1060.     // Check if we know what the image type is
  1061.     ASSERTM(ODISOStrEqual(imageType, kODDragImageRegionHandle), kODErrUnknownDragImageType, "Unknown image type in StartDrag");
  1062.  
  1063.     // Set the drop result to kODDropFail. - VL
  1064.     _fDropResult = kODDropFail;
  1065.     
  1066.     // Begin the drag by creating a new drag reference
  1067.     result = NewDrag(&_fDragReference);
  1068.     ASSERTM(result == noErr, result, "Bad result from NewDrag");
  1069.     
  1070. #ifdef ODDebug_DragAndDrop
  1071. //    PrintDragReference(_fDragReference, "After NewDrag");
  1072. #endif
  1073.  
  1074.     // Register a send procedure so we don't have to cache any data with the drag manager
  1075.     result = SetDragSendProc(_fDragReference, _fSendDataHandler, (void *) somSelf);
  1076.     ASSERTM(result == noErr, result, "Bad result from SetDragSendProc");
  1077.  
  1078.     // Scan through all items in the drag and add a flavor for each value
  1079.     // in the storage unit's kODContents property
  1080.     theIter = new LinkedListIterator(_fDragItemList);
  1081.     translate = _fSession->GetTranslation(ev);
  1082.     imageRgn = *((RgnHandle*) image->_buffer);
  1083.     for (theDragLink = (ODDragLink*)theIter->First(); theDragLink; theDragLink = (ODDragLink*)theIter->Next())
  1084.     {
  1085.         theSU = theDragLink->fItem->fSU;
  1086.         ODBoolean    userPromise = ODSUExistsThenFocus(ev, theSU, kODPropContents, kODHFSPromise);
  1087.         if (userPromise)
  1088.         {
  1089.             ODByteArray ba;
  1090.             ODPart* dummySourcePart;
  1091.             theSU->GetPromiseValue(ev, kODHFSPromise, 0, sizeof(PromiseHFSFlavor), &ba, &dummySourcePart);
  1092.             if (ba._buffer)
  1093.             {
  1094.                 ODBlockMove(ba._buffer, &thePromise, ba._length);
  1095.                 ODDisposePtr(ba._buffer);
  1096.             }
  1097.             thePromise.promisedFlavor = kODUserPromiseFlavor;
  1098.         }
  1099.         else {
  1100.             // Always promise a file in case somebody wishes to drag this out to the finder
  1101.             thePromise.fileType = kODBentoFlavor;
  1102.             thePromise.fileCreator = kODShellSignature;
  1103.             thePromise.fdFlags = 0;
  1104.             thePromise.promisedFlavor = kODBentoFlavor;
  1105.         }
  1106.         result = AddDragItemFlavor(_fDragReference, (ItemReference)(theDragLink->fItem), flavorTypePromiseHFS,
  1107.                                    &thePromise, sizeof(PromiseHFSFlavor), 0);
  1108.         ASSERTM(result == noErr, result, "Bad result from AddDragItemFlavor");
  1109.  
  1110.         result = AddDragItemFlavor(_fDragReference, (ItemReference)(theDragLink->fItem), (userPromise ? kODUserPromiseFlavor : kODBentoFlavor), 0L, 0L, 0);
  1111.         ASSERTM(result == noErr, result, "Bad result from AddDragItemFlavor");
  1112.         
  1113.         result = SetDragItemBounds(_fDragReference, (ItemReference)(theDragLink->fItem), &((**imageRgn).rgnBBox));
  1114.         ASSERTM(result == noErr, result, "Bad result from SetDragItemBounds");
  1115.  
  1116. #ifdef ODDebug_DragAndDrop
  1117. //    PrintStorageUnit(ev, theSU, "DragItem SU");
  1118. #endif
  1119.         theSU->Focus(ev,kODPropContents, kODPosUndefined, 0, 0, kODPosUndefined);
  1120.         count = theSU->CountValues(ev);
  1121.         for (index = 1; index <= count; ++index)
  1122.         {
  1123.             theSU->Focus(ev,kODPropContents, kODPosUndefined, 0, index, kODPosUndefined);
  1124.             theISOType = theSU->GetType(ev);
  1125.             platformType = translate->GetPlatformTypeFromISOType(ev, theISOType);
  1126.             ODDisposePtr(theISOType);
  1127.             if (!platformType)
  1128.                 continue;
  1129.             result = AddDragItemFlavor(_fDragReference, (ItemReference)(theDragLink->fItem), platformType, 0L, 0L, 0);
  1130.             ASSERTM(result == noErr, result, "Bad result from AddDragItemFlavor");
  1131.  
  1132.             // If styled text ('stxt') was just added, also add 'stly' if
  1133.             // a 'TEXT' representation will also be written.
  1134.             if (     (platformType == kODScrapTypestxt)
  1135.                   && theSU->Exists(ev, kODPropContents, kODAppleTEXT, 0)
  1136.                   && !theSU->Exists(ev, kODPropContents, kODApplestyl, 0) )
  1137.             {
  1138.                 result = AddDragItemFlavor(_fDragReference, (ItemReference)(theDragLink->fItem), kODScrapTypestyl, 0L, 0L, 0);
  1139.                 ASSERTM(result == noErr, result, "Bad result from AddDragItemFlavor");
  1140.             }
  1141.         }
  1142.     
  1143.         // Always add our special dummy promise to the drag
  1144.         result = AddDragItemFlavor(_fDragReference, (ItemReference)(theDragLink->fItem), kODPromiseFlavor, 0L, 0L, 0);
  1145.         ASSERTM(result == noErr, result, "Bad result from adding kODPromiseFlavor");
  1146.     }
  1147.     ODBoolean oldDelayFatal = gODDelayBentoFatalError;
  1148.     gODDelayBentoFatalError = kODTrue; // no exit to shell inside Drag Mgr
  1149.  
  1150.     _fSourceFrame = srcFrame;
  1151.     _fSourcePart = srcFrame->AcquirePart(ev);
  1152.     TRY
  1153.         _fDestFacet = kODNULL;
  1154.         _fDragItemIterator = new ODDragItemIterator();
  1155.         THROW_IF_NULL(_fDragItemIterator, kODErrOutOfMemory);
  1156.         _fDragItemIterator->InitDragItemIterator(ev, theIter);
  1157.         _fHasLeftSourceFrame = kODFalse;
  1158.         _fHasLeftSourcePart = kODFalse;
  1159.         
  1160.         #ifdef ODDebug_DragAndDrop
  1161.         //    PrintDragReference(_fDragReference, "Before TrackDrag");
  1162.         #endif
  1163.     
  1164.         // Do the drag    
  1165.         result = TrackDrag(_fDragReference, *((EventRecord**) refCon->_buffer), imageRgn);
  1166.     
  1167.         if (_fDestFacet)
  1168.             *destPart = _fDestFacet->GetFrame(ev)->AcquirePart(ev);
  1169.         else
  1170.             *destPart = kODNULL;
  1171.     CATCH_ALL
  1172.         DisposeDrag(_fDragReference);
  1173.         _fDragReference = kODNULL;
  1174.         ODReleaseObject(ev, _fSourcePart);
  1175.         RERAISE;
  1176.     ENDTRY
  1177.     
  1178.     gODDelayBentoFatalError = oldDelayFatal;
  1179.     if ( gODBentoFatalErrorHasOccurred && !gODDelayBentoFatalError )
  1180.         ODBentoFatalError();
  1181.         
  1182.     DisposeDrag(_fDragReference);
  1183.     _fDragReference = kODNULL;
  1184.     _fSourceFrame = kODNULL;
  1185.     ODReleaseObject(ev, _fSourcePart);
  1186.     _fDestFacet = kODNULL;
  1187.     somSelf->Clear(ev);
  1188.  
  1189.     if (_fShouldSendReplaceFileEvent)
  1190.     {
  1191.         _fShouldSendReplaceFileEvent = kODFalse;
  1192.         OSErr err = SetupReplaceFileEvent(ev,
  1193.             _fReplaceFileEvent,
  1194.             &gTmpFileFSSpec,
  1195.             &gTargetFSSpec);
  1196.         SendReplaceFileEvent(_fReplaceFileEvent, _fPSN);
  1197.         DisposeReplaceFileEvent(_fReplaceFileEvent);
  1198.         CreateReplaceFileEvent(ev,
  1199.             _fReplaceFileEvent,
  1200.             _fSession,
  1201.             _fPSN);
  1202.     }
  1203.  
  1204. SOM_CATCH_ALL
  1205.  
  1206.     delete theIter;
  1207.     if (_fDragReference)
  1208.         DisposeDrag(_fDragReference);
  1209.     _fDragReference = kODNULL;
  1210.     
  1211. SOM_ENDTRY
  1212.  
  1213.     if (_fDropResult == kODDropMove)
  1214.         return kODDropMove;
  1215.     else if (_fDropResult == kODDropCopy)
  1216.         return kODDropCopy;
  1217.     else
  1218.         return kODDropFail;
  1219. }
  1220.  
  1221.  
  1222. SOM_Scope LinkedList*  SOMLINK ODDragAndDropGetDragItemList(ODDragAndDrop *somSelf, Environment *ev)
  1223. {
  1224.     ODDragAndDropData *somThis = ODDragAndDropGetData(somSelf);
  1225.     ODDragAndDropMethodDebug("ODDragAndDrop","ODDragAndDropGetDragItemList");
  1226.  
  1227.     return _fDragItemList;
  1228. }
  1229.  
  1230. SOM_Scope void  SOMLINK ODDragAndDropSetDragItemList(ODDragAndDrop *somSelf, Environment *ev,
  1231.         LinkedList* list)
  1232. {
  1233.     ODDragAndDropData *somThis = ODDragAndDropGetData(somSelf);
  1234.     ODDragAndDropMethodDebug("ODDragAndDrop","ODDragAndDropSetDragItemList");
  1235.  
  1236.     _fDragItemList = list;
  1237. }
  1238.  
  1239. SOM_Scope ODBoolean  SOMLINK ODDragAndDropGetListFromHandler(ODDragAndDrop *somSelf, Environment *ev)
  1240. {
  1241.     ODDragAndDropData *somThis = ODDragAndDropGetData(somSelf);
  1242.     ODDragAndDropMethodDebug("ODDragAndDrop","ODDragAndDropGetListFromHandler");
  1243.  
  1244.     return _fListFromHandler;
  1245. }
  1246.  
  1247. SOM_Scope void  SOMLINK ODDragAndDropSetListFromHandler(ODDragAndDrop *somSelf, Environment *ev,
  1248.         ODBoolean listFromHandler)
  1249. {
  1250.     ODDragAndDropData *somThis = ODDragAndDropGetData(somSelf);
  1251.     ODDragAndDropMethodDebug("ODDragAndDrop","ODDragAndDropSetListFromHandler");
  1252.  
  1253.     _fListFromHandler = listFromHandler;
  1254. }
  1255.  
  1256. SOM_Scope ODFrame*  SOMLINK ODDragAndDropGetSourceFrame(ODDragAndDrop *somSelf, Environment *ev)
  1257. {
  1258.     ODDragAndDropData *somThis = ODDragAndDropGetData(somSelf);
  1259.     ODDragAndDropMethodDebug("ODDragAndDrop","ODDragAndDropGetSourceFrame");
  1260.  
  1261.     return _fSourceFrame;
  1262. }
  1263.  
  1264. SOM_Scope void  SOMLINK ODDragAndDropSetSourceFrame(ODDragAndDrop *somSelf, Environment *ev,
  1265.         ODFrame* sourceFrame)
  1266. {
  1267.     ODDragAndDropData *somThis = ODDragAndDropGetData(somSelf);
  1268.     ODDragAndDropMethodDebug("ODDragAndDrop","ODDragAndDropSetSourceFrame");
  1269.  
  1270.     _fSourceFrame = sourceFrame;
  1271. }
  1272.  
  1273. SOM_Scope ODULong  SOMLINK ODDragAndDropGetAttributes(ODDragAndDrop *somSelf, Environment *ev)
  1274. {
  1275.     ODDragAndDropData *somThis = ODDragAndDropGetData(somSelf);
  1276.     ODDragAndDropMethodDebug("ODDragAndDrop","ODDragAndDropGetAttributes");
  1277.  
  1278.     return _fAttributes;
  1279. }
  1280.  
  1281. SOM_Scope void  SOMLINK ODDragAndDropSetAttributes(ODDragAndDrop *somSelf, Environment *ev,
  1282.         ODULong attr)
  1283. {
  1284.     ODDragAndDropData *somThis = ODDragAndDropGetData(somSelf);
  1285.     ODDragAndDropMethodDebug("ODDragAndDrop","ODDragAndDropSetAttributes");
  1286.  
  1287.     _fAttributes = attr;
  1288. }
  1289.  
  1290. SOM_Scope ODPart*  SOMLINK ODDragAndDropGetSourcePart(ODDragAndDrop *somSelf, Environment *ev)
  1291. {
  1292.     ODDragAndDropData *somThis = ODDragAndDropGetData(somSelf);
  1293.     ODDragAndDropMethodDebug("ODDragAndDrop","ODDragAndDropGetSourcePart");
  1294.  
  1295.     return _fSourcePart;
  1296. }
  1297.  
  1298. SOM_Scope void  SOMLINK ODDragAndDropSetSourcePart(ODDragAndDrop *somSelf, Environment *ev,
  1299.         ODPart* sourcePart)
  1300. {
  1301.     ODDragAndDropData *somThis = ODDragAndDropGetData(somSelf);
  1302.     ODDragAndDropMethodDebug("ODDragAndDrop","ODDragAndDropSetSourcePart");
  1303.  
  1304.     _fSourcePart = sourcePart;
  1305. }
  1306.  
  1307. SOM_Scope ODDragItemIterator*  SOMLINK ODDragAndDropGetDragItemIterator(ODDragAndDrop *somSelf, Environment *ev)
  1308. {
  1309.     ODDragAndDropData *somThis = ODDragAndDropGetData(somSelf);
  1310.     ODDragAndDropMethodDebug("ODDragAndDrop","ODDragAndDropGetDragItemIterator");
  1311.  
  1312.     return _fDragItemIterator;
  1313. }
  1314.  
  1315. SOM_Scope void  SOMLINK ODDragAndDropSetDragItemIterator(ODDragAndDrop *somSelf, Environment *ev,
  1316.         ODDragItemIterator* iter)
  1317. {
  1318.     ODDragAndDropData *somThis = ODDragAndDropGetData(somSelf);
  1319.     ODDragAndDropMethodDebug("ODDragAndDrop","ODDragAndDropSetDragItemIterator");
  1320.  
  1321.     _fDragItemIterator = iter;
  1322. }
  1323.  
  1324. SOM_Scope ODSession*  SOMLINK ODDragAndDropGetSession(ODDragAndDrop *somSelf, Environment *ev)
  1325. {
  1326.     ODDragAndDropData *somThis = ODDragAndDropGetData(somSelf);
  1327.     ODDragAndDropMethodDebug("ODDragAndDrop","ODDragAndDropGetSession");
  1328.  
  1329.     return _fSession;
  1330. }
  1331.  
  1332. SOM_Scope ODStorageSystem*  SOMLINK ODDragAndDropGetStorageSystem(ODDragAndDrop *somSelf, Environment *ev)
  1333. {
  1334.     ODDragAndDropData *somThis = ODDragAndDropGetData(somSelf);
  1335.     ODDragAndDropMethodDebug("ODDragAndDrop","ODDragAndDropGetStorageSystem");
  1336.  
  1337.     return _fStorageSystem;
  1338. }
  1339.  
  1340. SOM_Scope void  SOMLINK ODDragAndDropSetDragReference(ODDragAndDrop *somSelf, Environment *ev,
  1341.         ODPlatformDragReference dragReference)
  1342. {
  1343.     ODDragAndDropData *somThis = ODDragAndDropGetData(somSelf);
  1344.     ODDragAndDropMethodDebug("ODDragAndDrop","ODDragAndDropSetDragReference");
  1345.     
  1346.     _fDragReference = dragReference;
  1347. }
  1348.  
  1349. SOM_Scope ODFacet*  SOMLINK ODDragAndDropGetPrevFacet(ODDragAndDrop *somSelf, Environment *ev)
  1350. {
  1351.     ODDragAndDropData *somThis = ODDragAndDropGetData(somSelf);
  1352.     ODDragAndDropMethodDebug("ODDragAndDrop","ODDragAndDropGetPrevFacet");
  1353.  
  1354.     return _fPrevFacet;
  1355. }
  1356.  
  1357. SOM_Scope void  SOMLINK ODDragAndDropSetPrevFacet(ODDragAndDrop *somSelf, Environment *ev,
  1358.         ODFacet* prevFacet)
  1359. {
  1360.     ODDragAndDropData *somThis = ODDragAndDropGetData(somSelf);
  1361.     ODDragAndDropMethodDebug("ODDragAndDrop","ODDragAndDropSetPrevFacet");
  1362.  
  1363.     _fPrevFacet = prevFacet;
  1364. }
  1365.  
  1366. SOM_Scope ODFacet*  SOMLINK ODDragAndDropGetDestFacet(ODDragAndDrop *somSelf, Environment *ev)
  1367. {
  1368.     ODDragAndDropData *somThis = ODDragAndDropGetData(somSelf);
  1369.     ODDragAndDropMethodDebug("ODDragAndDrop","ODDragAndDropGetDestFacet");
  1370.  
  1371.     return _fDestFacet;
  1372. }
  1373.  
  1374. SOM_Scope void  SOMLINK ODDragAndDropSetDestFacet(ODDragAndDrop *somSelf, Environment *ev,
  1375.         ODFacet* destFacet)
  1376. {
  1377.     ODDragAndDropData *somThis = ODDragAndDropGetData(somSelf);
  1378.     ODDragAndDropMethodDebug("ODDragAndDrop","ODDragAndDropSetDestFacet");
  1379.  
  1380.     _fDestFacet = destFacet;
  1381. }
  1382.  
  1383. SOM_Scope ODDropResult  SOMLINK ODDragAndDropGetDropResult(ODDragAndDrop *somSelf, Environment *ev)
  1384. {
  1385.     ODDragAndDropData *somThis = ODDragAndDropGetData(somSelf);
  1386.     ODDragAndDropMethodDebug("ODDragAndDrop","ODDragAndDropGetDropResult");
  1387.  
  1388.     return _fDropResult;
  1389. }
  1390.  
  1391. SOM_Scope void  SOMLINK ODDragAndDropSetDropResult(ODDragAndDrop *somSelf, Environment *ev,
  1392.         ODDropResult dropResult)
  1393. {
  1394.     ODDragAndDropData *somThis = ODDragAndDropGetData(somSelf);
  1395.     ODDragAndDropMethodDebug("ODDragAndDrop","ODDragAndDropSetDropResult");
  1396.  
  1397.     _fDropResult = dropResult;
  1398. }
  1399.  
  1400. SOM_Scope ProcessSerialNumber*   SOMLINK ODDragAndDropGetPSN(ODDragAndDrop *somSelf, Environment *ev)
  1401. {
  1402.     ODDragAndDropData *somThis = ODDragAndDropGetData(somSelf);
  1403.     ODDragAndDropMethodDebug("ODDragAndDrop","ODDragAndDropGetDropResult");
  1404.  
  1405.     return _fPSN;
  1406. }
  1407.  
  1408. SOM_Scope AppleEvent*   SOMLINK ODDragAndDropGetReplaceFileEvent(ODDragAndDrop *somSelf, Environment *ev)
  1409. {
  1410.     ODDragAndDropData *somThis = ODDragAndDropGetData(somSelf);
  1411.     ODDragAndDropMethodDebug("ODDragAndDrop","ODDragAndDropGetDropResult");
  1412.  
  1413.     return _fReplaceFileEvent;
  1414. }
  1415.  
  1416. SOM_Scope void   SOMLINK ODDragAndDropSetShouldSendReplaceFileEvent(ODDragAndDrop *somSelf, Environment *ev,
  1417.     ODBoolean shouldSend)
  1418. {
  1419.     ODDragAndDropData *somThis = ODDragAndDropGetData(somSelf);
  1420.     ODDragAndDropMethodDebug("ODDragAndDrop","ODDragAndDropGetDropResult");
  1421.  
  1422.     _fShouldSendReplaceFileEvent = shouldSend;
  1423. }
  1424.  
  1425. ODBoolean DragItemHasFlavor(ODPlatformDragReference theDrag, ItemReference itemID, OSType    theType)
  1426. {
  1427.     ODBoolean    result = kODFalse;
  1428.     ODUShort    count;            
  1429.     ODUShort    j;
  1430.     OSType        itemType;
  1431.  
  1432.     CountDragItemFlavors(theDrag, itemID, &count);
  1433.     for (j = 1; j <= count; j++)
  1434.     {
  1435.         OSErr err = GetFlavorType(theDrag, itemID, j, &itemType);
  1436.         if ( err != noErr )
  1437.             break;
  1438.         if (itemType == theType)
  1439.         {
  1440.             result = kODTrue;
  1441.             break;
  1442.         }
  1443.     }
  1444.  
  1445.     return result;
  1446. }
  1447.  
  1448. pascal OSErr MyDragTrackingHandler(
  1449.         short message,
  1450.         WindowPtr theWindow,
  1451.         void* handlerRefCon,
  1452.         ODPlatformDragReference theDrag)
  1453. {
  1454.     ODDragAndDrop  *self = (ODDragAndDrop*)handlerRefCon;
  1455.     ODPoint            mouse, localMouse;
  1456.     OSErr            returnCode = noErr;
  1457.  
  1458.     ODBoolean oldDelayFatal = gODDelayBentoFatalError;
  1459.     gODDelayBentoFatalError = kODTrue; // no exit to shell inside Drag Mgr
  1460.  
  1461.     TRY
  1462.     
  1463.         Environment*    ev = somGetGlobalEnvironment();
  1464.     
  1465.         switch (message)
  1466.         {
  1467.             case dragTrackingEnterHandler:
  1468.                 returnCode = self->EnterHandler(ev, theDrag);
  1469.                 break;            
  1470.             case dragTrackingEnterWindow:
  1471.                 returnCode = self->EnterWindow(ev, theDrag, theWindow);
  1472.                 break;
  1473.                 
  1474.             case dragTrackingInWindow:
  1475.                 returnCode = self->InWindow(ev, theDrag, theWindow);
  1476.                 break;
  1477.                 
  1478.             case dragTrackingLeaveWindow:
  1479.                 returnCode = self->LeaveWindow(ev, theDrag, theWindow);
  1480.                 break;
  1481.                 
  1482.             case dragTrackingLeaveHandler:
  1483.                 returnCode = self->LeaveHandler(ev);
  1484.                 break;
  1485.         }
  1486.     
  1487.     CATCH_ALL
  1488.     
  1489.         returnCode = ErrorCode();
  1490.     
  1491.     ENDTRY
  1492.  
  1493.     gODDelayBentoFatalError = oldDelayFatal;
  1494.  
  1495.     return returnCode;
  1496. }
  1497.  
  1498. pascal OSErr    MyReceiveDropHandler(
  1499.         WindowPtr theWindow,
  1500.         void* handlerRefCon,
  1501.         ODPlatformDragReference theDrag)
  1502. {
  1503.     ODDragAndDrop    *self = (ODDragAndDrop*)handlerRefCon;
  1504.     ODPoint            mouse, localMouse;
  1505.     Point            qdMouse;
  1506.     ODFacet            *targetFacet;
  1507.     OSErr            returnCode = noErr;
  1508.  
  1509. #ifdef ODDebug_DragAndDrop
  1510.     somPrintf("MyReceiveDropHandler\n");
  1511. #endif
  1512.  
  1513.     ODBoolean oldDelayFatal = gODDelayBentoFatalError;
  1514.     gODDelayBentoFatalError = kODTrue; // no exit to shell inside Drag Mgr
  1515.  
  1516.     Environment* ev = somGetGlobalEnvironment();
  1517.  
  1518. TRY
  1519.  
  1520.     GetDragMouse(theDrag, &qdMouse, 0L);
  1521.     mouse = qdMouse;
  1522.     targetFacet = self->FindTargetFacet(ev, theWindow, &mouse, &localMouse);
  1523.         
  1524.     if (!targetFacet || !(self->GetDragItemList(ev)->Count()))
  1525.         returnCode = dragNotAcceptedErr;
  1526.     else
  1527.     {
  1528.         TempODPart targetPart = targetFacet->GetFrame(ev)->AcquirePart(ev);
  1529.  
  1530.         // Assume _fDropResult is kODDropMove
  1531.         
  1532.         self->SetDropResult(ev, kODDropMove);
  1533.         
  1534.         // Are we going across Drafts?
  1535.         
  1536.         ODPart* sourcePart = self->GetSourcePart(ev);
  1537.         if ((sourcePart == kODNULL) || 
  1538.             (targetPart->GetStorageUnit(ev)->GetDraft(ev) != 
  1539.             sourcePart->GetStorageUnit(ev)->GetDraft(ev)))
  1540.             self->SetDropResult(ev, kODDropCopy);
  1541.  
  1542.         ODSShort    mouseDownModifiers;
  1543.         ODSShort    mouseUpModifiers;
  1544.                 
  1545.         GetDragModifiers(self->GetDragReference(ev), 0L, &mouseDownModifiers, &mouseUpModifiers);
  1546.  
  1547.         // Check the mandatory modifier keys first
  1548.         
  1549.         if (mouseUpModifiers & optionKey) {
  1550.             self->SetDropResult(ev, kODDropCopy);
  1551.             SetPasteAsAttribute(self, ev, mouseUpModifiers);
  1552.         }
  1553.         else if (mouseUpModifiers & controlKey) {
  1554.             self->SetDropResult(ev, kODDropMove);
  1555.             SetPasteAsAttribute(self, ev, mouseUpModifiers);
  1556.         }
  1557.         else if (mouseUpModifiers & cmdKey) {
  1558.             SetPasteAsAttribute(self, ev, mouseUpModifiers);
  1559.         }
  1560.  
  1561.         // Then check the optional modifier keys
  1562.         
  1563.         else if (mouseDownModifiers & optionKey) {
  1564.             self->SetDropResult(ev, kODDropCopy);
  1565.             SetPasteAsAttribute(self, ev, mouseDownModifiers);
  1566.         }
  1567.         else if (mouseDownModifiers & controlKey) {
  1568.             self->SetDropResult(ev, kODDropMove);
  1569.             SetPasteAsAttribute(self, ev, mouseDownModifiers);
  1570.         }
  1571.         else if (mouseDownModifiers & cmdKey) {
  1572.             SetPasteAsAttribute(self, ev, mouseDownModifiers);
  1573.         }
  1574.                     
  1575.         // Check to see whether it is an override by source part.
  1576.         ODDragItemIterator* dragItemIter = self->GetDragItemIterator(ev);
  1577.         if (dragItemIter)
  1578.         {
  1579.             ODStorageUnit* su = dragItemIter->First(ev);
  1580.             ODDraft* draft = su->GetDraft(ev);
  1581.             ODCloneKind cloneKind = GetOriginalCloneKind(ev, draft);
  1582.             if (cloneKind == kODCloneCopy)
  1583.                 self->SetDropResult(ev, kODDropCopy);
  1584.         }
  1585.         
  1586.         // Drop
  1587. #ifdef ODDebug_DragAndDrop
  1588.     somPrintf("Calling Drop on targetFacet %x\n", targetFacet);
  1589. #endif
  1590.  
  1591.         self->SetAttributes(ev, self->GetAttributes(ev) | 
  1592.                 (self->GetDropResult(ev) == kODDropMove ? kODDropIsMove : kODDropIsCopy));
  1593.                 
  1594.         if (targetFacet->GetFrame(ev) == self->GetSourceFrame(ev))
  1595.             self->SetAttributes(ev, self->GetAttributes(ev) | (kODDropIsInSourceFrame | kODDropIsInSourcePart));
  1596.         else if (targetPart == self->GetSourcePart(ev))
  1597.             self->SetAttributes(ev, self->GetAttributes(ev) | kODDropIsInSourcePart);
  1598.                 
  1599.         self->SetDestFacet(ev, targetFacet);
  1600.         self->SetPrevFacet(ev, kODNULL);
  1601.         ODULong dropResult = targetFacet->Drop(ev, &localMouse, self->GetDragItemIterator(ev), kODNULL);
  1602.  
  1603.         if (dropResult == kODDropFail) {
  1604.             self->SetDropResult(ev, dropResult);
  1605.             returnCode = dragNotAcceptedErr;
  1606.         }
  1607.         else if ((self->GetDropResult(ev) == kODDropMove) && (dropResult == kODDropCopy)) {
  1608.             self->SetDropResult(ev, kODDropCopy);
  1609.             returnCode = noErr;
  1610.         }
  1611.         
  1612.         ODDragItemIterator* iter = self->GetDragItemIterator(ev);
  1613.         ODSession* destSession = self->GetSession(ev);
  1614.         for (ODStorageUnit* su = iter->First(ev); iter->IsNotComplete(ev); su = iter->Next(ev)) {
  1615.             ODSession* sourceSession = su->GetSession(ev);
  1616.             if ((sourceSession != kODNULL) && (sourceSession != destSession)) {
  1617.                 ODDragAndDrop* sourceDAD = sourceSession->GetDragAndDrop(ev);
  1618.                 if (sourceDAD != kODNULL) {
  1619.                     sourceDAD->SetDropResult(ev, self->GetDropResult(ev));
  1620.                     sourceDAD->SetDestFacet(ev, targetFacet);
  1621.                 }
  1622.             }
  1623.         }
  1624. //            ODSession* sourceSession = sourcePart->AcquireStorageUnit(ev)->GetSession(ev);
  1625. //            if (sourceSession != self->GetSession(ev)) {
  1626. //                ODDragAndDrop* sourceDAD = sourceSession->GetDragAndDrop(ev);
  1627. //                sourceDAD->SetDropResult(ev, self->GetDropResult(ev));
  1628. //                sourceDAD->SetDestFacet(ev, targetFacet);
  1629. //            }
  1630. //        }
  1631.     }
  1632.  
  1633. CATCH_ALL
  1634.     gODDelayBentoFatalError = oldDelayFatal;
  1635.  
  1636.     self->SetDropResult(ev, kODDropFail);
  1637.     returnCode = dragNotAcceptedErr;
  1638. #if ODDebug            
  1639.     somPrintf("Error in MyReceiveDropHandler.\n");
  1640. #endif
  1641.  
  1642. ENDTRY
  1643.  
  1644.     gODDelayBentoFatalError = oldDelayFatal;
  1645.  
  1646.     ODEventData    event;
  1647.     WaitNextEvent(mUpMask, (EventRecord*) &event, 0, kODNULL);
  1648. #if ODDebug_DragAndDrop            
  1649.     somPrintf("message %x when %x where %x modifier %x\n", event.message, event.when, event.where, event.modifiers);
  1650. #endif
  1651.  
  1652.     return returnCode;
  1653. }
  1654.  
  1655. pascal OSErr  MySendDataProc(
  1656.         FlavorType theType,
  1657.         void* refCon,
  1658.         ItemReference theItem,
  1659.         ODPlatformDragReference theDrag)
  1660. {
  1661.     ODDragAndDrop    *self = (ODDragAndDrop*)refCon;
  1662.     Environment*    ev = somGetGlobalEnvironment();
  1663.     OSErr            result = noErr;
  1664.     ODType            theISOType;
  1665.     ODTranslation    *translate;
  1666.     AEDesc            dropDescriptor;
  1667.     ODPtr            stylPtr = kODNULL;
  1668.     ODULong            stylSize = 0;
  1669.  
  1670.     ODBoolean oldDelayFatal = gODDelayBentoFatalError;
  1671.     gODDelayBentoFatalError = kODTrue; // no exit to shell inside Drag Mgr
  1672.  
  1673. ODVolatile(result);
  1674. TRY
  1675.  
  1676.     LinkedListIterator iter(self->GetDragItemList(ev));
  1677.     ODDragLink*        theDragLink = kODNULL;
  1678.     ODMemDragItem*    theDragItem = kODNULL;
  1679.  
  1680. #ifdef ODDebug_DragAndDrop
  1681.     somPrintf("Entering MySendDataProc.\n");
  1682. #endif
  1683.  
  1684.     for (theDragLink = (ODDragLink*)iter.First(); 
  1685.          theDragLink; theDragLink = (ODDragLink*)iter.Next())
  1686.     {
  1687.         if (theDragLink->fItem == (ODDragItem*)theItem)
  1688.         {
  1689.             theDragItem = (ODMemDragItem*) theDragLink->fItem;
  1690.             break;
  1691.         }
  1692.     }
  1693.     if (!theDragItem)
  1694.     {
  1695.         WARN("Item not found in send proc");
  1696.         result =  badDragFlavorErr;
  1697.     }
  1698.     else {
  1699.         switch (theType)
  1700.         {
  1701.             case kODPromiseFlavor:
  1702. #ifdef ODDebug_DragAndDrop
  1703.     somPrintf("MySendDataProc: kODPromiseFlavor\n");
  1704. #endif
  1705.                 if (gIsResolvingPromise)
  1706.                 {
  1707.                     result = GetDropLocation(theDrag, &dropDescriptor);
  1708.                     if ((result != noErr) || (dropDescriptor.descriptorType != kODPromiseDesc)) {
  1709.                         WARN("Error from GetDropLocation in send procedure");
  1710.                     }
  1711.                     else {
  1712.                         ODPromiseDesc     theInfo;
  1713.                         ODBlockMove((Ptr)(*dropDescriptor.dataHandle), (Ptr)&theInfo, sizeof(ODPromiseDesc));
  1714.                         if (theInfo.sourcePart && theInfo.destSUView)
  1715.                         {
  1716.                             TRY
  1717.                                 theInfo.sourcePart->FulfillPromise(ev, theInfo.destSUView);
  1718.                             CATCH_ALL
  1719.                                 WARN("Error from FulfillPromise.");
  1720.                             ENDTRY
  1721.                         }
  1722.                     result = noErr;
  1723.                     }
  1724.                 }
  1725.             break;
  1726.             case kODUserPromiseFlavor:
  1727. #ifdef ODDebug_DragAndDrop
  1728.     somPrintf("MySendDataProc: kODUserPromiseFlavor\n");
  1729. #endif
  1730.                 result = noErr;
  1731.                 ODStorageUnit* contentSU = theDragItem->fSU;
  1732.                 if ((contentSU != kODNULL) && (contentSU->Exists(ev, kODPropContents, kODHFSPromise, 0)))
  1733.                 {
  1734.                     FSSpec dropFSSpec;
  1735.                     result = GetDropFSSpec(theDrag, dropFSSpec);
  1736.                     if (result == noErr)
  1737.                     {
  1738.                         TRY
  1739.                             contentSU->Focus(ev, kODPropContents, kODPosUndefined, kODHFSPromise, 0, kODPosUndefined);
  1740.                             StorageUnitSetPromiseValue(contentSU, ev, kODHFSPromise, 0, sizeof(FSSpec), &dropFSSpec, self->GetSourcePart(ev));
  1741.                             contentSU->Focus(ev, kODPropContents, kODPosUndefined, kODHFSPromise, 0, kODPosUndefined);
  1742.                             ODULong size = StorageUnitGetValue(contentSU, ev, sizeof(FSSpec), &dropFSSpec);
  1743.                             if (size != sizeof(FSSpec))
  1744.                             {
  1745.                                 self->SetDropResult(ev, kODDropFail);
  1746.                                 result = fnfErr;
  1747.                             }
  1748.                             else
  1749.                             {
  1750.                                 self->SetDropResult(ev, IsTrashFolder(dropFSSpec) ? kODDropMove : kODDropCopy);
  1751.                                 SetDragItemFlavorData(theDrag, theItem, theType, &dropFSSpec, sizeof(FSSpec), 0L);
  1752.                             }
  1753.                         CATCH_ALL
  1754.                             WARN("Error from FulfillPromise.");
  1755.                         ENDTRY
  1756.                     }
  1757.                     // If we get a file not found error, most likely we are trying to drag to somewhere other than the Finder.
  1758.                     // That's OK, so just eat the error.
  1759.                     if( result == fnfErr )
  1760.                         result = noErr;
  1761.                 }
  1762.             break;
  1763.             case kODBentoFlavor:
  1764.             {
  1765. #ifdef ODDebug_DragAndDrop
  1766.     somPrintf("MySendDataProc: kODBentoFlavor\n");
  1767. #endif
  1768.                 // Check the drop location (probably from the finder)
  1769.                 FSSpec dropFSSpec;
  1770.                 
  1771.                 result = GetDropFSSpec(theDrag, dropFSSpec);
  1772.                 if (result == noErr)
  1773.                 {
  1774.                     boolean nameFromPart = MakeUniqueFilename(ev, self->GetSession(ev), theDragItem->fSU, &dropFSSpec);
  1775.                     
  1776.                     // Drags to the Trash are always a move
  1777.                     ODULong dropResult;
  1778.                     boolean isDraggingToTrash = IsTrashFolder(dropFSSpec);
  1779.                     if( isDraggingToTrash )
  1780.                         dropResult = kODDropMove;        // Dragged to Trash, so it's a move
  1781.                     else
  1782.                         dropResult = kODDropCopy;
  1783.                     self->SetDropResult(ev, dropResult);
  1784.     
  1785.                     if (isDraggingToTrash)
  1786.                     {
  1787.                         TempPlatformFile file = new PlatformFile;
  1788.                         file->Specify(&dropFSSpec);
  1789.     
  1790.                         if (file->Exists())
  1791.                         {
  1792.                             // If the target file exists in trash already,
  1793.                             // set the fsspec to the temp folder.
  1794.                             RespecifyToTempFolder(file);
  1795.                             
  1796.                             // Clone the data.
  1797.                             CloneIntoFile(ev, theDragItem, file->GetFileSpec());
  1798.                             
  1799.                             // After cloning the data to the file (in temp folder),
  1800.                             // move to it trash.
  1801.                             file->MoveToTrash();
  1802.                             
  1803.                             // Set the result for Drag Manager.
  1804.                             SetDragItemFlavorData(theDrag, theItem, theType, &(file->GetFileSpec()), sizeof(FSSpec), 0L);
  1805.                         }
  1806.                         else
  1807.                         {
  1808.                             CloneIntoFlavor(ev, self, theDragItem,
  1809.                                             theDrag, theItem, theType,
  1810.                                             dropFSSpec);
  1811.                         }
  1812.                     }
  1813.                     else if (!nameFromPart)
  1814.                     {
  1815.                         CloneIntoFlavor(ev, self, theDragItem,
  1816.                                         theDrag, theItem, theType,
  1817.                                         dropFSSpec);
  1818.                     }
  1819.                     else if (IsFrontProcess())
  1820.                     {
  1821.                         TempPlatformFile file = new PlatformFile;
  1822.                         file->Specify(&dropFSSpec);
  1823.     
  1824.                         if (file->Exists())
  1825.                         {
  1826.                             ParamText(dropFSSpec.name, "\p", "\p", "\p");
  1827.                             if (ODAskUserReplace(ev, self->GetSession(ev)))
  1828.                             {                        
  1829.                                 file->MoveToTrash();
  1830.                                 CloneIntoFlavor(ev, self, theDragItem,
  1831.                                                 theDrag, theItem, theType,
  1832.                                                 dropFSSpec);
  1833.                             }
  1834.                         }
  1835.                         else
  1836.                         {
  1837.                             CloneIntoFlavor(ev, self, theDragItem,
  1838.                                             theDrag, theItem, theType,
  1839.                                             dropFSSpec);
  1840.                         }
  1841.                     }
  1842.                     else
  1843.                     {
  1844.                         TempPlatformFile file = new PlatformFile;
  1845.                         file->Specify(&dropFSSpec);
  1846.                         
  1847.                         if (file->Exists())
  1848.                         {
  1849.                             FSSpec targetFSSpec = file->GetFileSpec();
  1850.                             RespecifyToTempFolder(file);
  1851.                             FSSpec tmpFileFSSpec = file->GetFileSpec();
  1852.                             CloneIntoFile(ev, theDragItem, tmpFileFSSpec);
  1853.                             // Not notifying the target through SetDragItemData on purpose becuase we are going all the work.
  1854.                             
  1855.                             gTargetFSSpec = targetFSSpec;
  1856.                             gTmpFileFSSpec = tmpFileFSSpec;
  1857.                             self->SetShouldSendReplaceFileEvent(ev, kODTrue);
  1858.                         }
  1859.                         else
  1860.                         {
  1861.                             CloneIntoFlavor(ev, self, theDragItem,
  1862.                                         theDrag, theItem, theType,
  1863.                                         dropFSSpec);
  1864.                         }                
  1865.                     }
  1866.                 }
  1867.                 // If we are not dragging to a file, create a Drag item for the Bento Container.
  1868.                 // This allows other applications to support OpenDoc Bento types (like the Scrapbook, 
  1869.                 // or Container apps).
  1870.                 else if ( result == fnfErr )
  1871.                 {
  1872.                     // At this point, Doug says only a memory container is being modified in any way,
  1873.                     // so we can suppress fatal errors:
  1874.                     ODBoolean oldSuppress = gODSuppressBentoFatalError;
  1875.                     gODSuppressBentoFatalError = kODTrue;
  1876.                     
  1877.                     OSErr e = 
  1878.                     CopyMemContainerToDragItemInChunks( ev, self->GetSession(ev), theType, theItem, theDrag, theDragItem );
  1879.  
  1880.                     gODSuppressBentoFatalError = oldSuppress; // neutral
  1881.  
  1882.                     return e;
  1883.                 }
  1884.             }
  1885.             break;
  1886.             default:
  1887. #ifdef ODDebug_DragAndDrop
  1888.     somPrintf("MySendDataProc: Default\n");
  1889. #endif
  1890.                 self->SetDropResult(ev, kODDropFail);
  1891.                 translate = self->GetSession(ev)->GetTranslation(ev);
  1892.                 theISOType = translate->GetISOTypeFromPlatformType(ev, theType, kODPlatformDataType);
  1893.                 if (ODSUExistsThenFocus(ev, theDragItem->fSU,kODPropContents, theISOType))
  1894.                 {
  1895.                     result = CopyToDragItemInChunks(ev, theType, theItem, theDrag, theDragItem);
  1896.                     if (result == noErr)
  1897.                         self->SetDropResult(ev, kODDropCopy);
  1898.                 }
  1899.                 else if ( (theType == kODScrapTypestyl) && StorageUnitGetStylFromStyledText(theDragItem->fSU, ev, &stylSize, &stylPtr) )
  1900.                 {
  1901.                     result = SetDragItemFlavorData(theDrag, theItem, theType, stylPtr, stylSize, 0L);
  1902.                     WASSERTM(result == noErr, "Error from SetDragItemFlavorData in send procedure");        
  1903.                     if (result == noErr)
  1904.                         self->SetDropResult(ev, kODDropCopy);
  1905.                     ODDisposePtr(stylPtr);
  1906.                     stylPtr = kODNULL;
  1907.                 }
  1908.                 else
  1909.                 {
  1910.                     WARN("Send procedure can not supply this type");        
  1911.                     result = badDragFlavorErr;
  1912.                 }
  1913.                 ODDisposePtr(theISOType);
  1914.             }
  1915.         }
  1916.  
  1917. CATCH_ALL
  1918.     gODDelayBentoFatalError = oldDelayFatal;
  1919.     self->SetShouldSendReplaceFileEvent(ev, kODFalse);
  1920.     result = ErrorCode();
  1921.     WARN("MySendDataProc: %d", result); 
  1922. ENDTRY
  1923.     gODDelayBentoFatalError = oldDelayFatal;
  1924.     
  1925.     return result;
  1926. }
  1927.  
  1928. static OSErr CopyMemContainerToDragItemInChunks(Environment* ev,
  1929.                                 ODSession* theSession,
  1930.                                 FlavorType theType,
  1931.                                 ItemReference theItem,
  1932.                                 ODPlatformDragReference theDrag,
  1933.                                 ODDragItem* theDragItem) 
  1934. {
  1935.     const ODULong kCopyBlockSize = 512;
  1936.     OSErr    result = noErr;
  1937.     ODPtr     dataPtr;
  1938.     ODULong dataSize;
  1939.     
  1940.     TRY
  1941.         // Now write out the entire Container for the Memory Drag item.
  1942.         ODMemDragItem* tempDItem = (ODMemDragItem*)theDragItem;
  1943.  
  1944.         // Clone the D&D container to a temp draft, then return the data handle from the temp container.
  1945.         // We cannot directly get the data handle from the D&D container, because the full data isn't written
  1946.         // until we close the container, but we can't do that yet because there could be further promises
  1947.         // pending against it.
  1948.         TempODHandle theMemDragItemContainerData = CloneToTempMemContainer( ev,  tempDItem, theSession );        
  1949.  
  1950.         ODLockHandle( theMemDragItemContainerData );
  1951.     
  1952.         dataPtr = *theMemDragItemContainerData;
  1953.         dataSize = ODGetHandleSize( theMemDragItemContainerData );
  1954.         WASSERTM( dataSize != 0, "Zero size memory container handle.");        
  1955.  
  1956.         ODULong currentByte = 0;
  1957.         while ((currentByte < dataSize) && (result == noErr)) {
  1958.             ODULong bytesRead;
  1959.             if( ( dataSize - currentByte )  >= kCopyBlockSize )
  1960.                 bytesRead = kCopyBlockSize;
  1961.             else
  1962.                 bytesRead = dataSize - currentByte;
  1963.                 
  1964.             result = SetDragItemFlavorData(theDrag, theItem, theType, ODPtr((ODULong)dataPtr + currentByte), bytesRead, currentByte);
  1965.             WASSERTM(result == noErr, "Error from SetDragItemFlavorData in CopyToDragItemInChunks.");        
  1966.             currentByte += bytesRead;
  1967.         }
  1968.         WASSERTM(currentByte == dataSize, "Bytes written is NOT equal to dataSize.");        
  1969.     CATCH_ALL
  1970.         result = dragNotAcceptedErr;
  1971.     ENDTRY
  1972.     return result;
  1973. }
  1974.  
  1975. static ODHandle CloneToTempMemContainer( Environment* ev, ODMemDragItem* tempDItem, ODSession* theSession )
  1976. {
  1977.     ODStorageUnit* contentSU = tempDItem->fSU;
  1978.     ODID targetContentFrameID = kODNULLID;
  1979.     ODHandle containerHandle =    ODNewHandle(0);
  1980.     ODStorageUnitID suID;
  1981.     TRY
  1982.         TempODContainer        tempContainer = CreateMemoryContainer(ev, theSession, containerHandle, kODBentoMemoryContainer);        
  1983.         TempODDocument         tempDocument = tempContainer->AcquireDocument(ev, kODDefaultDocument);
  1984.         TempODDraft         targetDraft = tempDocument->AcquireBaseDraft(ev, kODDPExclusiveWrite);
  1985.         TempODStorageUnit    targetSU    = targetDraft->CreateStorageUnit(ev);
  1986.  
  1987.         { TempODStorageUnit draftProperties = targetDraft->AcquireDraftProperties(ev);
  1988.           ODSetStrongSURefProp(ev, draftProperties, kODPropRootPartSU, kODStrongStorageUnitRef,targetSU->GetID(ev));
  1989.           suID = ODGetStrongSURefProp(ev, draftProperties, kODPropRootPartSU, kODStrongStorageUnitRef);
  1990.         }
  1991.         
  1992.         ODDraft* sourceDraft = contentSU->GetDraft(ev);                
  1993.         ODDraftKey cloneKey = 0;
  1994.         TRY
  1995.             cloneKey = sourceDraft->BeginClone(ev, targetDraft, kODNULL, kODCloneToFile);
  1996.             sourceDraft->Clone(ev, cloneKey, contentSU->GetID(ev), targetSU->GetID(ev), 0);                
  1997.             ODID contentFrameID = ODGetWeakSURefProp(ev, contentSU, kODPropContentFrame, kODWeakStorageUnitRef);
  1998.             if (contentFrameID != kODNULLID) 
  1999.             {
  2000.                 targetContentFrameID = sourceDraft->Clone(ev, cloneKey, contentFrameID, kODNULLID, 0);                
  2001.             }        
  2002.             sourceDraft->EndClone(ev, cloneKey);
  2003.         CATCH_ALL
  2004.             sourceDraft->AbortClone(ev, cloneKey);
  2005.             
  2006.         ENDTRY
  2007.         
  2008.         ODSURemoveProperty(ev, targetSU, kODPropMouseDownOffset);    
  2009.  
  2010.         // first externalize the container 
  2011.         // Externalize may fail with an iterator-out-of-sync error because 
  2012.         // resolving promises may add storage units to the draft's collection
  2013.         // during iteration.  In theory, the only promises should be in the
  2014.         // root storage unit, so explicitly externalize it first to resolve
  2015.         // promises before interating over all storage units.
  2016.         if( targetSU )
  2017.             targetSU->Externalize(ev);
  2018.         targetDraft->Externalize(ev);
  2019.         
  2020.     CATCH_ALL
  2021.         ODDisposeHandle( containerHandle );
  2022.         RERAISE;
  2023.     ENDTRY
  2024.     
  2025.     return containerHandle; 
  2026. }
  2027.  
  2028. static void CloneIntoFlavor(Environment* ev, ODDragAndDrop* dad, ODDragItem* theDragItem, 
  2029.                                 ODPlatformDragReference theDrag, ItemReference theItem, FlavorType theType,
  2030.                                 FSSpec dropFSSpec)
  2031. {
  2032.     OSErr result;
  2033.     
  2034.     if ((result = CloneIntoFile(ev, theDragItem, dropFSSpec)) == noErr)
  2035.     {
  2036.         result = SetDragItemFlavorData(theDrag, theItem, theType, &dropFSSpec, sizeof(FSSpec), 0L);
  2037.     }
  2038.     else
  2039.     {
  2040.         dad->SetDropResult(ev, kODDropFail);                
  2041.     }                
  2042. }
  2043.  
  2044. static OSErr CloneIntoFile(Environment* ev, ODDragItem* theDragItem, FSSpec dropFSSpec) 
  2045. {
  2046.     OSErr            err = noErr;
  2047.     PlatformFile    file;
  2048.     file.Specify(&dropFSSpec);
  2049.     
  2050.     TRY
  2051.         ODStorageUnit* contentSU = theDragItem->fSU;
  2052.         ODID targetContentFrameID = kODNULLID;
  2053.         OSType    fileType = GetStorageUnitOSType(ev,contentSU);
  2054.  
  2055.         file.Create(kODShellSignature, fileType, smSystemScript);
  2056.         SetFinderInfo(ev, contentSU, &file);
  2057.         SetIconFamily(ev, contentSU, &file);
  2058.         TempODContainer targetContainer    = CreateFileContainer(ev, contentSU->GetSession(ev), &file.GetFileSpec());
  2059.         TempODDocument    targetDocument    = targetContainer->AcquireDocument(ev, kODDefaultDocument);
  2060.         TempODDraft        targetDraft     = targetDocument->AcquireBaseDraft(ev, kODDPExclusiveWrite);
  2061.         TempODStorageUnit     targetDraftProperties = targetDraft->AcquireDraftProperties(ev);
  2062.         TempODStorageUnit    targetSU    = targetDraft->CreateStorageUnit(ev);
  2063.         ODSetStrongSURefProp(ev, targetDraftProperties, kODPropRootPartSU,kODStrongStorageUnitRef, targetSU->GetID(ev));
  2064.         ODDraft* sourceDraft = contentSU->GetDraft(ev);                
  2065.         ODDraftKey cloneKey = 0;
  2066.         TRY
  2067.             cloneKey = sourceDraft->BeginClone(ev, targetDraft, kODNULL, kODCloneToFile);
  2068.             sourceDraft->Clone(ev, cloneKey, contentSU->GetID(ev), targetSU->GetID(ev), 0);                
  2069.             ODID contentFrameID = ODGetWeakSURefProp(ev, contentSU, kODPropContentFrame, kODWeakStorageUnitRef);
  2070.             if (contentFrameID != kODNULLID) 
  2071.             {
  2072.                 targetContentFrameID = sourceDraft->Clone(ev, cloneKey, contentFrameID, kODNULLID, 0);                
  2073.             }        
  2074.             sourceDraft->EndClone(ev, cloneKey);
  2075.         CATCH_ALL
  2076.             sourceDraft->AbortClone(ev, cloneKey);
  2077.         ENDTRY
  2078.         
  2079.         if (targetContentFrameID != kODNULLID)
  2080.             ODSetStrongSURefProp(ev, targetDraftProperties, kODPropRootFrameList, kODStrongStorageUnitRefs, targetContentFrameID);
  2081.  
  2082.         ODSURemoveProperty(ev, targetSU, kODPropMouseDownOffset);
  2083.  
  2084.         targetDraft->Externalize(ev);        
  2085.  
  2086.                 
  2087.     CATCH_ALL
  2088.     
  2089.         file.Delete();        
  2090.         err = dragNotAcceptedErr;
  2091.         WARN("Error caught in CloneIntoFile.");
  2092.     ENDTRY
  2093.     
  2094.     return err;
  2095. }
  2096.  
  2097. static boolean MakeUniqueFilename( Environment *ev, ODSession* session, ODStorageUnit *su, FSSpec* spec )
  2098. {
  2099.     const ODULong kODMaxFileNameSize = 63;
  2100.     
  2101.     Str255 prefix;
  2102.     prefix[0] = 0;
  2103.     boolean nameFromPart = false;
  2104.     TempPlatformFile file = new PlatformFile;
  2105.     file->Specify(spec);
  2106.     
  2107.     TRY
  2108.         // Get the name of the part
  2109.         if (su->Exists(ev, kODPropName, kODMacIText, 0))
  2110.         {
  2111.             ODIText* rootPartName = ODGetITextProp(ev, su, kODPropName, kODMacIText, kODNULL);
  2112.             if (rootPartName)
  2113.             {
  2114.                 GetITextPString(rootPartName, prefix);
  2115.                 DisposeIText(rootPartName);
  2116.                 p2cstr(prefix);
  2117.                 file->SetAsciiName((char*) prefix);    
  2118.                 nameFromPart = true;
  2119.             }
  2120.         }
  2121.     
  2122.         if (!prefix[0])
  2123.         {        
  2124.             // Get the category of the part if a name cannot be found.
  2125.             ODName* categoryName = kODNULL;
  2126.             TRY
  2127.                 categoryName = ODGetCatFromPartSU(ev, su, session->GetNameSpaceManager(ev));
  2128.             CATCH_ALL
  2129.             ENDTRY
  2130.             // If the above call throws, then most likely we were trying to get the category for NoPart.
  2131.             // So, set the category name for NoPart appropriately.
  2132.             if( !categoryName)
  2133.             {
  2134.                 ODGetString( prefix, kODUnknownCategoryStr );
  2135.                 p2cstr(prefix);
  2136.             }
  2137.             if (categoryName)
  2138.             {
  2139.                 GetITextPString(categoryName, prefix);
  2140.                 p2cstr(prefix);
  2141.             }
  2142.             file->SetAsciiName((char*) prefix);    
  2143.             file->UniquifyName(kODNoResourceID,
  2144.                                 kODNULL,
  2145.                                 kODCategoryNumberSuffix,
  2146.                                 kODNULL,
  2147.                                 1,
  2148.                                 kSpecifyNewNameOnly,
  2149.                                 kODForceNewName);
  2150.             ODDisposePtr(categoryName);
  2151.             nameFromPart = false;
  2152.         }
  2153.     CATCH_ALL
  2154.     ENDTRY
  2155.         
  2156.     *spec = file->GetFileSpec();
  2157.     return nameFromPart;
  2158. }
  2159.  
  2160. static OSType GetStorageUnitOSType( Environment *ev, ODStorageUnit *su )
  2161. {
  2162.     OSType    returnType = kODShellSignature;
  2163.  
  2164. #if ODDebug_DragAndDrop
  2165.     ODULong    numProperties = su->CountProperties(ev);
  2166.     su->Focus(ev, kODNULL, kODPosAll, kODNULL, 0, kODPosAll);
  2167.     for (ODULong i = 1; i <= numProperties; i++) {
  2168.         su->Focus(ev, kODNULL, kODPosNextSib,kODNULL,0,kODPosAll);
  2169.         ODPropertyName name = su->GetProperty(ev);
  2170.         ODDisposePtr(name);
  2171.     }
  2172. #endif
  2173.     
  2174.     returnType = ODGetIconFilePlatformTypeFromPartSU(ev, su);
  2175.     
  2176.     /*
  2177.     //ODGetIconFilePlatformTypeFromPartSU is more correct than the below code:
  2178.     
  2179.     if (su->Exists(ev, kODPropContents,kODNULL,1)) {
  2180.         su->Focus(ev, kODPropContents,kODPosUndefined,kODNULL,1,kODPosUndefined);
  2181.         ODType suType = su->GetType(ev);
  2182.         if(suType != kODNULL) {
  2183.             ODValueNameSpace* osTypeNameSpace = (ODValueNameSpace*)
  2184.                         su->GetSession(ev)->GetNameSpaceManager(ev)->HasNameSpace(ev,kODKindOldMacOSType);
  2185.             if (osTypeNameSpace) {
  2186.                 ODOSType*   osTypePtr;
  2187.                 ODOSType    osType;
  2188.                 ODULong        valueLen;
  2189.                 ODBoolean    osTypeFound = ValueNameSpaceGetEntry(
  2190.                                             osTypeNameSpace, 
  2191.                                        ev, 
  2192.                                        suType, 
  2193.                                               (ODPtr*) &osTypePtr,
  2194.                                             &valueLen);
  2195.                 if (osTypeFound) {
  2196.                     osType = *osTypePtr;
  2197.                     ODDeleteObject( osTypePtr );
  2198.                     
  2199.                     WASSERT(valueLen==sizeof(OSType));
  2200.                     returnType = osType;
  2201.                 }
  2202.                 // SS: Begin Code Changes
  2203.                 else {
  2204.                     ODTranslation* translate = ODGetSession(ev,su)->GetTranslation(ev);
  2205.                     ODOSType osType = (ODOSType)translate->GetPlatformTypeFromISOType(ev, suType);
  2206.                     
  2207.                     if ( osType != kODNULL )
  2208.                     {
  2209.                         returnType = osType;
  2210.                         ((ODUByte*)(&returnType))[0] = kODPlatformKindFileChar1;
  2211.                     }
  2212.                 }
  2213.                 // SS: End Code Changes
  2214.             }
  2215.         }
  2216.     }
  2217.     */
  2218.     return returnType;
  2219. }
  2220.  
  2221.  
  2222. static OSErr CopyToDragItemInChunks(Environment* ev,
  2223.                                 FlavorType theType,
  2224.                                 ItemReference theItem,
  2225.                                 ODPlatformDragReference theDrag,
  2226.                                 ODDragItem* theDragItem) 
  2227. {
  2228.     const ODULong kCopyBlockSize = 512;
  2229.     OSErr    result = noErr;
  2230.     ODPtr     dataPtr = ODNewPtr(kCopyBlockSize);
  2231.     ODULong dataSize = theDragItem->fSU->GetSize(ev);
  2232.     
  2233.     ODULong currentByte = 0;
  2234.     while ((currentByte < dataSize) && (result == noErr)) {
  2235.         ODULong bytesRead = StorageUnitGetValue(theDragItem->fSU, ev, kCopyBlockSize, dataPtr);
  2236.         result = SetDragItemFlavorData(theDrag, theItem, theType, dataPtr, bytesRead, currentByte);
  2237.         WASSERTM(result == noErr, "Error from SetDragItemFlavorData in CopyToDragItemInChunks.");        
  2238.         currentByte += bytesRead;
  2239.     }
  2240.     ODDisposePtr(dataPtr);
  2241.     WASSERTM(currentByte == dataSize, "Bytes written is NOT equal to dataSize.");        
  2242.     
  2243.     return result;
  2244. }
  2245.  
  2246. static OSErr CopyFromDragItemInChunks(Environment* ev,
  2247.                                 FlavorType theType,
  2248.                                 ItemReference theItem,
  2249.                                 ODPlatformDragReference theDrag,
  2250.                                 ODStorageUnitView* destSUView) 
  2251. {
  2252.     const ODULong kCopyBlockSize = 512;
  2253.     OSErr    result = noErr;
  2254.     ODPtr     dataPtr = ODNewPtr(kCopyBlockSize);
  2255.     long    dataSize = 0;
  2256.     ODULong    totalRead = 0;
  2257.     ODULong    oldValueSize = destSUView->GetSize(ev);
  2258.     
  2259.     result = GetFlavorDataSize(theDrag, theItem, theType, &dataSize);
  2260.     while ((totalRead < dataSize) && (result == noErr)) {
  2261.         Size bytesRead = dataSize - totalRead;
  2262.         if (bytesRead > kCopyBlockSize)
  2263.             bytesRead = kCopyBlockSize;
  2264.         result = GetFlavorData(theDrag, theItem, theType, dataPtr, &bytesRead, totalRead);
  2265.         WASSERTM(result == noErr, "Error from GetFlavorData in CopyFromDragItemInChunks.");        
  2266.         StorageUnitViewSetValue(destSUView, ev, bytesRead, dataPtr);
  2267.         totalRead += bytesRead;
  2268.     }
  2269.     ODDisposePtr(dataPtr);
  2270.  
  2271.     ODULong newValueSize = destSUView->GetOffset(ev);
  2272.     if (oldValueSize > newValueSize)
  2273.         destSUView->DeleteValue(ev, oldValueSize - newValueSize);
  2274.  
  2275.     return result;
  2276. }
  2277.  
  2278.  
  2279. #ifdef ODDebug_DragAndDrop
  2280. void PrintDragReference(ODPlatformDragReference dragRef, char* header)
  2281. {
  2282.     unsigned short    items = 0;
  2283.     CountDragItems(dragRef, &items);
  2284.     somPrintf("%s: fDragReference %x numItems %d\n", header, dragRef, items);
  2285.     for (unsigned short i = 1; i <= items; i++) {
  2286.         ItemReference    itemRef;
  2287.         GetDragItemReferenceNumber(dragRef, i, &itemRef);
  2288.         unsigned short numFlavors = 0;
  2289.         CountDragItemFlavors(dragRef, itemRef, &numFlavors);
  2290.         FlavorType theType;
  2291.         Size    dataSize = 0;
  2292.         for (unsigned short j = 1; j <= numFlavors; j++) {
  2293.             GetFlavorType (dragRef, itemRef, j, &theType);
  2294.             GetFlavorDataSize(dragRef, itemRef, theType, &dataSize);
  2295.             somPrintf("%s: itemRef %x item %d flavor %d size %d type ", header, itemRef, i, j, dataSize);
  2296.             for (short k = 0; k <= 3; k++) {
  2297.                 somPrintf("%c", ((char*) &theType)[k]);
  2298.             }
  2299.             somPrintf("\n");
  2300.             if ((theType == 'hfs ') && (dataSize > 0)) {
  2301.                 HFSFlavor hfsFlavor;
  2302.                 GetFlavorData(dragRef,itemRef,theType,&hfsFlavor,&dataSize,0);
  2303.                 somPrintf("type %x creator %x name %s\n", hfsFlavor.fileType, hfsFlavor.fileCreator, p2cstr(hfsFlavor.fileSpec.name));
  2304.             }
  2305.         }
  2306.     }
  2307. }
  2308.  
  2309. void PrintStorageUnit(Environment* ev, ODStorageUnit* su, char* header)
  2310. {
  2311.     ODStorageUnitCursor* cursor = su->CreateCursorWithFocus(ev);
  2312.     
  2313.     ODULong numProperties = su->CountProperties(ev);
  2314.     su->Focus(ev, kODPropContents, kODPosUndefined, kODNULL, 0, kODPosUndefined);
  2315.     ODULong numValues = su->CountValues(ev);
  2316.     somPrintf("%s: su %x numProperties %d numContentValues %d\n", header, su, numProperties, numValues);
  2317.     for (short i = 1; i <= numValues; i++) {
  2318.         su->Focus(ev, kODNULL, kODPosSame, kODNULL, i, kODPosUndefined);
  2319.         ODValueType type = su->GetType(ev);
  2320.         somPrintf("%s: Type %d %s\n", header, i, type);
  2321.         ODDisposePtr(type);
  2322.     }
  2323.     
  2324.     su->FocusWithCursor(ev, cursor);
  2325.     delete cursor;
  2326. }
  2327.  
  2328. #endif
  2329.  
  2330. SOM_Scope OSErr  SOMLINK ODDragAndDropEnterHandler(ODDragAndDrop *somSelf, Environment *ev,
  2331.         ODPlatformDragReference theDrag)
  2332. {
  2333.     ODDragAndDropData *somThis = ODDragAndDropGetData(somSelf);
  2334.     ODDragAndDropMethodDebug("ODDragAndDrop","ODDragAndDropEnterHandler");
  2335.  
  2336. #if ODDebug_DragAndDrop
  2337.     somPrintf("In EnterHandler.\n");
  2338. #endif        
  2339.  
  2340.     OSErr            returnCode = noErr;
  2341.  
  2342.     ODVolatile(returnCode);
  2343.     SOM_TRY
  2344.         OSErr            result = noErr;
  2345.         ODDragLink*        newLink = kODNULL;
  2346.         ODUShort        items = 0;
  2347.         
  2348.         CountDragItems(theDrag, &items);
  2349.         for (ODUShort i = 1; i <= items; ++i)
  2350.         {
  2351.             ItemReference    itemID;
  2352.             FlavorFlags        theFlags;
  2353.             GetDragItemReferenceNumber(theDrag, i, &itemID);
  2354.             result = GetFlavorFlags(theDrag, itemID, kODPromiseFlavor, &theFlags);
  2355.             if (result == noErr) {
  2356.                 if (_fDragReference != theDrag)
  2357.                 {
  2358.                     _fListFromHandler = kODTrue;
  2359.                     newLink = new ODDragLink((ODDragItem*)itemID, kODFalse);
  2360.                     _fDragItemList->AddLast((Link*)newLink);
  2361.                 }
  2362.             }
  2363.             else if (result == badDragFlavorErr) {
  2364.                 ODStorageSystem*    storage = _fStorageSystem;
  2365.                 ODTranslation*        translate = _fSession->GetTranslation(ev);
  2366.                 ODDragItem*            newItem = kODNULL;        ODVolatile(newItem);
  2367.                 
  2368.                 ODUShort    count;            
  2369.                 ODUShort    j = 1;
  2370.                 HFSFlavor    hfsFlavor;
  2371.                 PlatformFile*    finderFile = kODNULL;
  2372.                 CountDragItemFlavors(theDrag, itemID, &count);
  2373.                 for (j = 1; (j <= count) && (newItem == kODNULL); j++) {
  2374.                     OSType    theType;
  2375.                     OSErr    err         = GetFlavorType(theDrag, itemID, j, &theType);
  2376.                     if ((err == noErr) && (theType == flavorTypeHFS)) {
  2377.                         Size            dataSize = sizeof(HFSFlavor);
  2378.                         OSErr err = GetFlavorData(theDrag, itemID, theType, &hfsFlavor, (Size*) &dataSize, 0);
  2379.                         if (err == noErr)
  2380.                         {
  2381.                             FSSpec targetFileSpec = hfsFlavor.fileSpec;
  2382.                             if ((hfsFlavor.fileCreator == kODShellSignature) &&
  2383.                                 IsOpenDocDocument(hfsFlavor.fileType))
  2384.                             {
  2385.                                 ODBoolean wasAliased;
  2386.                                 ODBoolean targetIsFolder;
  2387.                                 OSErr err = ResolveAliasFile(&targetFileSpec, TRUE, &targetIsFolder, &wasAliased);
  2388.                                 if ((err == noErr)  && (!targetIsFolder)) {
  2389.                                     FInfo    finderInfo;
  2390.                                     err = FSpGetFInfo(&targetFileSpec, &finderInfo);
  2391.                                     if ((err == noErr) && IsOpenDocDocument(finderInfo.fdType)) {
  2392.                                         ODByteArray*    ba = CreateByteArray(&targetFileSpec, sizeof(FSSpec));
  2393.                                         TRY
  2394.                                             newItem = new(ODGetDefaultHeap()) ODFileDragItem(storage, kODTrue);
  2395.                                             ((ODFileDragItem*) newItem)->Initialize(ev, ba);
  2396.                                         CATCH_ALL
  2397.                                             delete newItem;
  2398.                                             newItem = kODNULL;
  2399.                                         ENDTRY
  2400.                                         DisposeByteArray(ba);
  2401.                                     }
  2402.                                 }
  2403.                             }
  2404.                             finderFile = new PlatformFile();
  2405.                             finderFile->Specify(&targetFileSpec);
  2406.                         }
  2407.                     }
  2408.                     if( theType == kODBentoFlavor )
  2409.                     {
  2410.                         ODHandle tempHandle;
  2411.                         ODVolatile( tempHandle );
  2412.                         TRY
  2413.                             Size theSize;
  2414.                             OSErr err  = GetFlavorDataSize( theDrag, itemID, theType, &theSize );
  2415.                             tempHandle = ODNewHandle( theSize );
  2416.                             ODLockHandle( tempHandle );
  2417.                             err = GetFlavorData(theDrag, itemID, theType, *tempHandle, (Size*) &theSize, 0);
  2418.                             ODUnlockHandle(tempHandle);
  2419.                             newItem = new(ODGetDefaultHeap()) ODMemDragItem(storage, tempHandle, kODTrue);
  2420.                             ((ODMemDragItem*) newItem)->Open(ev);
  2421.                         CATCH_ALL
  2422.                             if( newItem )
  2423.                             {
  2424.                                 ODDeleteObject( newItem );
  2425.                             }
  2426.                             else
  2427.                             {
  2428.                                 ODDisposeHandle( tempHandle );
  2429.                             }
  2430.  
  2431.                         ENDTRY
  2432.                     }
  2433.                 }
  2434.                 if (newItem == kODNULL) {
  2435.                     newItem = new(ODGetDefaultHeap()) ODMemDragItem(storage, kODTrue);
  2436.                     ((ODMemDragItem*) newItem)->Initialize(ev);
  2437.                 }
  2438.                 ODStorageUnit*    su = newItem->fSU;
  2439.                 if (finderFile)
  2440.                 {
  2441.                     GetFinderInfo(ev, su, finderFile);
  2442.                     GetIconFamilyFromFile(ev, su, finderFile);
  2443.                     delete finderFile;
  2444.                 }
  2445.                 ODSUForceFocus(ev, su, kODPropContents, kODNULL);
  2446.                 for (j = 1; j <= count; j++) {
  2447.                     OSType            theType;
  2448.                     OSErr err = GetFlavorType(theDrag, itemID, j, &theType);
  2449.                     ODValueType isoType = translate->GetISOTypeFromPlatformType(ev, theType, kODPlatformDataType);
  2450.                     su->Focus(ev, kODPropContents, kODPosUndefined, kODNULL, 0, kODPosUndefined);
  2451.                     StorageUnitSetPromiseValue(su, ev, isoType, 0, sizeof(ItemReference), &itemID, kODNULL);
  2452.                     ODDisposePtr(isoType);
  2453.                     // If theType is 'styl', add a promise for 'stxt'
  2454.                     if ( theType == kODScrapTypestyl )
  2455.                     {
  2456.                         if ( DragItemHasFlavor(theDrag, itemID, kODScrapTypeTEXT) && !DragItemHasFlavor(theDrag, itemID, kODScrapTypestxt) )
  2457.                             StorageUnitSetPromiseValue(su, ev, kODApplestxt, 0, sizeof(ItemReference), &itemID, kODNULL);
  2458.                     }
  2459.                     else if (theType == flavorTypeHFS)
  2460.                     {
  2461.                         ODValueType isoType = translate->GetISOTypeFromPlatformType(ev, hfsFlavor.fileType, kODPlatformFileType);
  2462.                         su->AddValue(ev, isoType);
  2463.                         ODDisposePtr(isoType);
  2464.                     }
  2465.                 }
  2466.                 _fListFromHandler = kODTrue;
  2467.                 newLink = new ODDragLink(newItem, kODTrue);
  2468.                 _fDragItemList->AddLast((Link*)newLink);
  2469.             }
  2470.             else
  2471.             {
  2472.                 WASSERTM(result == noErr, "Error from GetFlavorFlags in tracking handler");
  2473.                 returnCode = result;
  2474.                 break;
  2475.             }
  2476.         }
  2477.         _fDragReference = theDrag;
  2478.         _fAttributes = 0;
  2479.         if (_fListFromHandler)
  2480.         {
  2481.             LinkedListIterator*    newIter = new LinkedListIterator(_fDragItemList);
  2482.             ODDragItemIterator* tmpIter = new ODDragItemIterator();
  2483.             THROW_IF_NULL(tmpIter, kODErrOutOfMemory);
  2484.             tmpIter->InitDragItemIterator(ev, newIter);
  2485.             _fDragItemIterator = tmpIter;
  2486.         }
  2487.     
  2488.         ODDeleteObject(_fFacetsRejected);
  2489.         
  2490.     SOM_CATCH_ALL    
  2491.     
  2492.         returnCode = ErrorCode();
  2493.         ODDeleteObject(_fFacetsRejected);
  2494.         if (_fDragItemList)
  2495.             _fDragItemList->DeleteAllLinks();
  2496.         
  2497.     SOM_ENDTRY
  2498.  
  2499.     _fFacetsRejected = new OpenHashTable(OpenHashTable::StdEqual, OpenHashTable::StdHash, kODNULL);
  2500.     _fFacetsRejected->Initialize(kODInitialNumEntries,
  2501.                                     sizeof(ODFacet*),
  2502.                                     sizeof(ODFacet*));
  2503.     
  2504.     return returnCode;
  2505. }
  2506.  
  2507. SOM_Scope OSErr  SOMLINK ODDragAndDropEnterWindow(ODDragAndDrop *somSelf, Environment *ev,
  2508.         ODPlatformDragReference theDrag,
  2509.         ODPlatformWindow theWindow)
  2510. {
  2511.     ODDragAndDropData *somThis = ODDragAndDropGetData(somSelf);
  2512.     ODDragAndDropMethodDebug("ODDragAndDrop","ODDragAndDropEnterWindow");
  2513.     
  2514.     // This is a private method called only from MyDragTrackingHandler.
  2515.     // It can do without its own SOM_TRY.
  2516.  
  2517. #if ODDebug_DragAndDrop
  2518.     somPrintf("Enter EnterWindow.\n");
  2519. #endif
  2520.  
  2521.     ODPoint            mouse, localMouse;
  2522.     Point            qdMouse;
  2523.     ODFacet*        targetFacet = kODNULL;
  2524.     ODBoolean        handled = kODFalse;
  2525.     
  2526.     GetDragMouse(theDrag, &qdMouse, 0L);
  2527.     mouse = qdMouse;
  2528.     targetFacet = somSelf->FindTargetFacet(ev, theWindow, &mouse, &localMouse);
  2529.     if (!targetFacet)
  2530.         _fAttributes &= kODDragHasLeftSourcePartMask;
  2531.     else
  2532.     {
  2533.         while (targetFacet && !handled)
  2534.         {
  2535.             if ((targetFacet->GetFrame(ev) == _fSourceFrame) && (_fHasLeftSourceFrame == kODFalse)) {
  2536.                 _fAttributes |= kODDragIsInSourcePart;
  2537.                 _fAttributes |= kODDragIsInSourceFrame;
  2538.             }
  2539.             else
  2540.             {
  2541.                 _fHasLeftSourceFrame = kODTrue;
  2542.                 ODPart* targetPart = targetFacet->GetFrame(ev)->AcquirePart(ev);
  2543.                 if (targetPart == _fSourcePart)
  2544.                     _fAttributes = kODDragIsInSourcePart;
  2545.                 else {
  2546.                     _fHasLeftSourcePart = kODTrue;
  2547.                     _fAttributes = 0;
  2548.                 }
  2549.                 ODReleaseObject(ev, targetPart);
  2550.             }
  2551.             handled = targetFacet->DragEnter(ev, &localMouse, _fDragItemIterator, kODNULL);
  2552.             if (!handled)
  2553.             {
  2554.                 _fFacetsRejected->ReplaceEntry(&targetFacet, &targetFacet);
  2555.                 targetFacet = somSelf->FindTargetFacet(ev, theWindow, &mouse, &localMouse);
  2556.             }
  2557.         }
  2558.     }
  2559.     _fPrevFacet = targetFacet;
  2560.     
  2561.     return noErr;
  2562. }
  2563.  
  2564. SOM_Scope OSErr  SOMLINK ODDragAndDropInWindow(ODDragAndDrop *somSelf, Environment *ev,
  2565.         ODPlatformDragReference theDrag,
  2566.         ODPlatformWindow theWindow)
  2567. {
  2568.     ODDragAndDropData *somThis = ODDragAndDropGetData(somSelf);
  2569.     ODDragAndDropMethodDebug("ODDragAndDrop","ODDragAndDropInWindow");
  2570.  
  2571.     ODPoint            mouse, localMouse;
  2572.     Point            qdMouse;
  2573.     ODFacet*        targetFacet = kODNULL;
  2574.     ODBoolean        handled = kODFalse;
  2575.     
  2576.     SOM_TRY
  2577.     
  2578.         GetDragMouse(theDrag, &qdMouse, 0L);
  2579.         mouse = qdMouse;
  2580.         // Get the facet under the current mouse location.
  2581.         targetFacet = somSelf->FindTargetFacet(ev, theWindow, &mouse, &localMouse);
  2582.         
  2583.         // We are leaving the window, call DragLeave on the last facet and return
  2584.         if (!targetFacet) {
  2585.             _fAttributes &= kODDragHasLeftSourcePartMask;
  2586.             if (_fPrevFacet) {
  2587.                 _fPrevFacet->DragLeave(ev, &localMouse, kODNULL);
  2588.             }
  2589.         }
  2590.         // Otherwise, the mouse is still in the OpenDoc window.
  2591.         else
  2592.         {    
  2593.             // Since the mouse is still in the OpenDoc window, we want to implement the following protocal for
  2594.             // having different facets draw drag highlighting. Everytime the mouse moves and is still in the window:
  2595.             // A. If the mouse enters a new facet, call DragEnter on the new one.
  2596.             //       1. If the new facet can't accept the drag, call DragEnter on the next containg facet.
  2597.             // B. If the mouse stays within the same facet, call DragWithin on that facet again.
  2598.             // C. If the mouse leaves a facet, call DragLeave on the facet.
  2599.             // We don't want drag-highlighiting to take place on the frame that originates the drag,
  2600.             // unless the mouse leaves the frame, then enters it again. So, we do the following:
  2601.             //    1. Store a refernce to the frame that originated the drag..
  2602.             //      2. Define a boolean that signifies that the mouse has not left the source frame.
  2603.             //      3. While the mouse is still in the source frame, tell the part not to do any drag-hiliting as above.
  2604.             //      4. When the mouse leaves the source frame, set the boolean that signifies we have not left the source
  2605.             //         to false. This tells subsequent parts to do hilighting following the above algorithm.
  2606.  
  2607.             // We basically want to do one of the following in this loop:
  2608.             //    1. Track that the mouse has entered a new facet and call DragEnter on it.
  2609.             //    2. Track that the mouse has left a facet and call DragLeave on it.
  2610.             //    3. Track that the mouse is still in a facet and call DragWithin on it.
  2611.             // Obviously there are special cases to all of the above. See the source comments below for more info.
  2612.             while (targetFacet && !handled)
  2613.             {   
  2614.                 // Check whether we are still in the source frame, and haven't ever left it. If so, no hiliting needed.
  2615.                 if ((targetFacet->GetFrame(ev) == _fSourceFrame) && (_fHasLeftSourceFrame == kODFalse)) {
  2616.                     _fAttributes |= kODDragIsInSourcePart;
  2617.                     _fAttributes |= kODDragIsInSourceFrame;
  2618.                 }
  2619.                 // Otherwise, we are either in a new frame, or we have left and reenter the source frame. 
  2620.                 // Tell the part to start doing hiliting.
  2621.                 else {
  2622.                     _fHasLeftSourceFrame = kODTrue;
  2623.                     ODPart* targetPart = targetFacet->GetFrame(ev)->AcquirePart(ev);
  2624.                     if (targetPart == _fSourcePart)
  2625.                         _fAttributes = kODDragIsInSourcePart;
  2626.                     else {
  2627.                         _fHasLeftSourcePart = kODTrue;
  2628.                         _fAttributes = 0;
  2629.                     }
  2630.                     ODReleaseObject(ev, targetPart);
  2631.                 }
  2632.                 if (_fPrevFacet == targetFacet)  {
  2633.                     handled = targetFacet->DragWithin(ev, &localMouse, _fDragItemIterator, kODNULL);
  2634.                 }
  2635.                 else {
  2636.                 // We need to call DragLeave on the previous facet before we call DragEnter on the new one, even
  2637.                 // though the DragEnter can return false. Why not call DragEnter first, decide if it succeeds, then
  2638.                 // call DragLeave? Because of ShowDragHilite and HideDragHilite Drag Manager functions need this
  2639.                 // order or drag hiliting is messed up.
  2640.                     if( _fPrevFacet )
  2641.                         _fPrevFacet->DragLeave(ev, &localMouse, kODNULL);
  2642.                     handled = targetFacet->DragEnter(ev, &localMouse, _fDragItemIterator, kODNULL);
  2643.     //                if ( _fPrevFacet && !handled ) {
  2644.     //                    targetFacet->DragEnter(ev, &localMouse, _fDragItemIterator, kODNULL);
  2645.     //                }
  2646.                 }
  2647.                 if (!handled)
  2648.                 {
  2649.                 // If any facet rejects a particular drag, then at no time during the current will it ever
  2650.                 // accept it again. A part can only handle certain drag kinds, and that will not change during
  2651.                 // a drag. So, if a drag is rejected, keep a list of facets that have rejected the current
  2652.                 // drag and don't try to do hiliting for them again for this drag.
  2653.                     _fFacetsRejected->ReplaceEntry(&targetFacet, &targetFacet); 
  2654.                     // On of the following happened previous to this statement:
  2655.                     // DragWithin or DragEnter was called on a facet and the part returned false.
  2656.                     // So, give the container a crack at the drag.
  2657.                     targetFacet = somSelf->FindTargetFacet(ev, theWindow, &mouse, &localMouse);
  2658.                     if( targetFacet )
  2659.                         targetFacet->DragEnter(ev, &localMouse, _fDragItemIterator, kODNULL);
  2660.                     // else the root rejected the drag and there is no container to take the drag. Will just
  2661.                     // exit this loop.
  2662.                 }
  2663.             }
  2664.         }
  2665.         _fPrevFacet = targetFacet;
  2666.     
  2667.     SOM_CATCH_ALL
  2668.     SOM_ENDTRY
  2669.  
  2670.     return noErr;
  2671. }
  2672.  
  2673. SOM_Scope OSErr  SOMLINK ODDragAndDropLeaveWindow(ODDragAndDrop *somSelf, Environment *ev,
  2674.         ODPlatformDragReference theDrag,
  2675.         ODPlatformWindow theWindow)
  2676. {
  2677.     ODDragAndDropData *somThis = ODDragAndDropGetData(somSelf);
  2678.     ODDragAndDropMethodDebug("ODDragAndDrop","ODDragAndDropLeaveWindow");
  2679.  
  2680. #if ODDebug_DragAndDrop
  2681.     somPrintf("In LeaveWindow.\n");
  2682. #endif        
  2683.  
  2684.     SOM_TRY
  2685.         ODPoint            mouse, localMouse;
  2686.         Point            qdMouse;
  2687.         
  2688.         GetDragMouse(theDrag, &qdMouse, 0L);
  2689.         mouse = qdMouse;
  2690.         ODFacet* dummyTargetFacet = somSelf->FindTargetFacet(ev, theWindow, &mouse, &localMouse);
  2691.     
  2692.         _fAttributes = 0;
  2693.         if (_fPrevFacet) {
  2694.             _fPrevFacet->DragLeave(ev, &localMouse, kODNULL);
  2695.             _fPrevFacet = kODNULL;
  2696.         }
  2697.     SOM_CATCH_ALL
  2698.     ENDTRY
  2699.     
  2700.     _fHasLeftSourceFrame = kODTrue;
  2701.     _fHasLeftSourcePart = kODTrue;
  2702.  
  2703.     return noErr;
  2704. }
  2705.  
  2706. SOM_Scope OSErr  SOMLINK ODDragAndDropLeaveHandler(ODDragAndDrop *somSelf, Environment *ev)
  2707. {
  2708.     ODDragAndDropData *somThis = ODDragAndDropGetData(somSelf);
  2709.     ODDragAndDropMethodDebug("ODDragAndDrop","ODDragAndDropLeaveHandler");
  2710.  
  2711. #if ODDebug_DragAndDrop
  2712.     somPrintf("In LeaveHandler.\n");
  2713. #endif        
  2714.     
  2715.     // Now undo the damage done in the dragTrackingEnterHandler section.
  2716.     // NOTE: It is OK to blow away the drag items here because at this point
  2717.     // the drop handler will already have processed the drop if any.
  2718.     if (_fListFromHandler)
  2719.     {
  2720.         TRY{
  2721.             somSelf->Clear(ev);
  2722.         }CATCH_ALL{
  2723.             // ignore error
  2724.         }ENDTRY
  2725.         _fListFromHandler = kODFalse;
  2726.         _fDragReference = 0;
  2727.     }
  2728.     _fAttributes = 0;
  2729.     
  2730.     return noErr;
  2731. }
  2732.  
  2733. static void    SetIconFamily(Environment* ev, ODStorageUnit* fromSU, PlatformFile* file)
  2734. {
  2735.     static const ResType            kIconType[6] = {'ICN#','icl4','icl8','ics#','ics4','ics8'};
  2736.     static const short                kIconSize[6] = {256,   512,   1024,  64,    128,   256   };
  2737.      ODIconFamily icons = ODGetIconFamilyProp(ev, fromSU, kODPropCustomIcon, kODIconFamily, kAllIconsMask);
  2738.     
  2739.     if (icons)
  2740.     {
  2741.         // write icons to the file
  2742.         long    i = 6;
  2743.         do {
  2744.             Handle    icon;
  2745.             char    state;
  2746.             if ((GetIconFromSuite(&icon, icons, kIconType[--i]) == noErr) && (icon != nil))
  2747.             {
  2748.                 state = HGetState(icon);
  2749.                 HLock(icon);
  2750.                 WASSERT(GetHandleSize(icon) == kIconSize[i]);
  2751.                 file->WriteResourcePtr(kIconType[i], kCustomIconResource, *icon, kIconSize[i]);
  2752.                 HSetState(icon, state);
  2753.             }
  2754.         } while (i);
  2755.         file->SetCustomIcon(kODTrue);
  2756.     }
  2757. }
  2758.  
  2759. static void SetFinderInfo(Environment* ev, ODStorageUnit* su, PlatformFile* file)
  2760. {
  2761.     InitDateInfo(ev, su);
  2762.     ODULong modDate = ODGetModificationDate(ev, su);
  2763.     ODULong creationDate = ODGetCreationDate(ev, su);        
  2764.     
  2765.     file->CreateResFile();    
  2766.     file->SetFileModDate(modDate);
  2767.     file->SetFileCreationDate(creationDate);
  2768.     file->SetStationery(ODGetSUIsStationery(ev, su));
  2769. }
  2770.  
  2771. static OSErr GetDropFSSpec(ODPlatformDragReference theDrag, FSSpec &dropFSSpec)
  2772. {
  2773.     AEDesc    dropDescriptor;
  2774.  
  2775.     OSErr result = GetDropLocation(theDrag, &dropDescriptor);
  2776.     if ((result != noErr) ||
  2777.         (dropDescriptor.descriptorType == typeNull) ||
  2778.         (dropDescriptor.dataHandle == nil))
  2779.     {
  2780.         result = fnfErr;            // Can't create a file unless we know where it goes!
  2781.     }
  2782.     else
  2783.     {
  2784.         AEDesc fssDescriptor;
  2785.         result = AECoerceDesc(&dropDescriptor, typeFSS, &fssDescriptor);
  2786.         AEDisposeDesc(&dropDescriptor);
  2787.         if (result == noErr) {        
  2788.             ODBlockMove(*fssDescriptor.dataHandle, &dropFSSpec, sizeof(FSSpec));
  2789.             AEDisposeDesc(&fssDescriptor);
  2790.  
  2791.             // Use PBGetCatInfo to get the directoryID of the target directory.
  2792.             CInfoPBRec getInfoPB;
  2793.             getInfoPB.dirInfo.ioCompletion = 0L;
  2794.             getInfoPB.dirInfo.ioNamePtr = (StringPtr) &(dropFSSpec.name);
  2795.             getInfoPB.dirInfo.ioVRefNum = dropFSSpec.vRefNum;
  2796.             getInfoPB.dirInfo.ioFDirIndex = 0;
  2797.             getInfoPB.dirInfo.ioDrDirID = dropFSSpec.parID;
  2798.             result = PBGetCatInfoSync(&getInfoPB);
  2799.             if (result == noErr)
  2800.             {
  2801.                 dropFSSpec.parID = getInfoPB.dirInfo.ioDrDirID;
  2802.                 dropFSSpec.name[0] = 0;
  2803.             }
  2804.         }
  2805.     }
  2806.     
  2807.     return result;
  2808. }
  2809.  
  2810. static boolean IsTrashFolder(FSSpec dropFSSpec)
  2811. {
  2812.     short trashVol;
  2813.     long trashDir;
  2814.  
  2815.     return (FindFolder(dropFSSpec.vRefNum,kTrashFolderType,kDontCreateFolder,&trashVol,&trashDir) == noErr) && 
  2816.             (trashVol==dropFSSpec.vRefNum) && (
  2817.             (trashDir==dropFSSpec.parID) );
  2818.  
  2819. }
  2820.  
  2821. static boolean IsFrontProcess()
  2822. {
  2823.     ProcessSerialNumber myProcess, frontProcess;
  2824.     boolean inFront = false;
  2825.  
  2826.     GetCurrentProcess(&myProcess);
  2827.     GetFrontProcess(&frontProcess);
  2828.     SameProcess(&myProcess, &frontProcess, &inFront);
  2829.  
  2830.     return inFront;
  2831. }
  2832.  
  2833. static OSErr CreateReplaceFileEvent(Environment* ev,
  2834.     AppleEvent* replaceFileEvent,
  2835.     ODSession* session,
  2836.     ProcessSerialNumber* psn)
  2837. {
  2838.     OSErr            err = noErr;
  2839.     AEAddressDesc    targetAddress;
  2840.     TempAEDesc        tempTargetAddress = kODNULL;
  2841.     
  2842.     err = AECreateDesc(typeProcessSerialNumber, psn, sizeof(ProcessSerialNumber), &targetAddress);
  2843.  
  2844.     if (err == noErr)
  2845.     {
  2846.         err = AECreateAppleEvent(kODShellSignature, kODReplaceFileEventID, 
  2847.                 &targetAddress, kAutoGenerateReturnID, 
  2848.                 kAnyTransactionID, replaceFileEvent);
  2849.         AEDisposeDesc(&targetAddress);
  2850.     }
  2851.     if ( err == noErr )
  2852.         err = AEPutParamPtr(replaceFileEvent, kODSession, typeLongInteger,
  2853.                             &session, sizeof(ODSession*));
  2854.     return err;
  2855. }
  2856.  
  2857. static OSErr SetupReplaceFileEvent(Environment* ev,
  2858.     AppleEvent* replaceFileEvent,
  2859.     FSSpec* sourceFileSpec,
  2860.     FSSpec* destFileSpec)
  2861. {
  2862.     OSErr err = noErr;
  2863.     if (err == noErr)
  2864.     {
  2865.         err = AEPutParamPtr(replaceFileEvent, kODSourceFileSpec, typeFSS,
  2866.                         sourceFileSpec, sizeof(FSSpec));
  2867.     }
  2868.     if ( err == noErr )
  2869.         err = AEPutParamPtr(replaceFileEvent, kODDestinationFileSpec, typeFSS,
  2870.                             destFileSpec, sizeof(FSSpec));
  2871.  
  2872. #ifdef ODDebug                    
  2873.     if (err != noErr)
  2874.     {
  2875.         WARN("Error in SetupReplaceFileEvent: %d", err);
  2876.     }
  2877. #endif
  2878.  
  2879.     return err;
  2880. }
  2881.  
  2882. static OSErr SendReplaceFileEvent(AppleEvent* replaceFileEvent, ProcessSerialNumber* psn)
  2883. {
  2884.     OSErr        err;
  2885.     AppleEvent    replyAppleEvent;
  2886.     
  2887.     SetFrontProcess(psn);
  2888.     
  2889. //    TempAEDesc tmpReplaceFileAppleEvent(replaceFileEvent);
  2890.     err = AESend(replaceFileEvent, &replyAppleEvent, kAENoReply | kAEInteractWithSelf,
  2891.                         kAENormalPriority, kAEDefaultTimeout, NULL, NULL);
  2892.  
  2893. #ifdef ODDebug                    
  2894.     if (err != noErr)
  2895.     {
  2896.         WARN("Error in SendReplaceFileEvent: %d", err);
  2897.     }
  2898. #endif
  2899.                             
  2900.     return err;
  2901. }
  2902.  
  2903. static OSErr DisposeReplaceFileEvent(AppleEvent* replaceFileEvent)
  2904. {
  2905.     return AEDisposeDesc(replaceFileEvent);
  2906. }
  2907.  
  2908. static OSErr ODPascal ReplaceFileAEHandler(
  2909.         const AppleEvent* replaceFileEvent,
  2910.         AppleEvent* reply,
  2911.         long refCon)
  2912. {
  2913.     OSErr        err = noErr;
  2914.     DescType    returnedType;
  2915.     Size        actualSize;
  2916.     FSSpec        sourceFileSpec;
  2917.     FSSpec        destFileSpec;
  2918.     ODSession*    session = kODNULL;
  2919.     
  2920.     err = AEGetParamPtr(replaceFileEvent, kODSession,
  2921.                             typeLongInteger, &returnedType,
  2922.                             &session, sizeof(ODSession*), &actualSize);
  2923.     WASSERTM(actualSize == sizeof(ODSession*), "Incorrect kODSession size");
  2924.     
  2925.     if (err == noErr)
  2926.     {
  2927.         err = AEGetParamPtr(replaceFileEvent, kODDestinationFileSpec,
  2928.                                 typeFSS, &returnedType,
  2929.                                 &destFileSpec, sizeof(FSSpec), &actualSize);
  2930.         WASSERTM(actualSize == sizeof(FSSpec), "Incorrect DestinationFileSpec size");
  2931.     }
  2932.     
  2933.     if (err == noErr)
  2934.     {
  2935.         Environment* ev = somGetGlobalEnvironment();
  2936.         ParamText(destFileSpec.name, "\p", "\p", "\p");
  2937.         err = AEInteractWithUser(kAEDefaultTimeout, NULL, NULL);
  2938.         if ((err == noErr) && ODAskUserReplace(ev, session))
  2939.         {
  2940.             err = AEGetParamPtr(replaceFileEvent, kODSourceFileSpec,
  2941.                                     typeFSS, &returnedType,
  2942.                                     &sourceFileSpec, sizeof(FSSpec), &actualSize);
  2943.             if (err == noErr)
  2944.             {
  2945.                 WASSERTM(actualSize == sizeof(FSSpec), "Incorrect kODSourceFileSpec size");
  2946.                 TempPlatformFile sourceFile = new PlatformFile;
  2947.                 sourceFile->Specify(&sourceFileSpec);
  2948.                 TempPlatformFile destFile = new PlatformFile;
  2949.                 destFile->Specify(&destFileSpec);
  2950.                 
  2951.                 destFile->MoveToTrash();
  2952.                 sourceFile->Move(destFileSpec.parID);
  2953.             }
  2954.         }
  2955.     }
  2956.  
  2957. #ifdef ODDebug
  2958.     if (err != noErr)
  2959.         WARN("Error occured in ReplaceFileAEHandler: %d", err);
  2960. #endif
  2961.  
  2962.     return err;
  2963. }
  2964.  
  2965. static void RespecifyToTempFolder(PlatformFile* file)
  2966. {
  2967.     ODSLong    tempDirID;
  2968.     FSSpec    fsSpec = file->GetFileSpec();
  2969.     
  2970.     THROW_IF_ERROR(FindFolder(fsSpec.vRefNum, kTemporaryFolderType, kCreateFolder,
  2971.                             &(fsSpec.vRefNum), &tempDirID));
  2972.     fsSpec.parID = tempDirID;
  2973.     file->Specify(&fsSpec);
  2974.     if (file->Exists())
  2975.         file->Delete();
  2976. }
  2977.             
  2978.